Пример #1
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
Пример #2
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
Пример #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
Пример #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)
Пример #5
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)
Пример #6
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
Пример #7
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
Пример #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
Пример #9
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
Пример #10
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
Пример #11
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
Пример #12
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
Пример #13
0
    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)
Пример #14
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)
Пример #15
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
Пример #16
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)
Пример #17
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)
Пример #18
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
Пример #19
0
 def _send_zrinit(self, timeout):
     log.debug('Sending ZRINIT header')
     header = [ZRINIT, 0, 0, 0, 4 | ZF0_CANFDX | ZF0_CANOVIO | ZF0_CANFC32]
     self._send_hex_header(header, timeout)
Пример #20
0
 def _send_zrinit(self, timeout):
     log.debug('Sending ZRINIT header')
     header = [ZRINIT, 0, 0, 0, 4 | ZF0_CANFDX | ZF0_CANOVIO | ZF0_CANFC32]
     self._send_hex_header(header, timeout)
Пример #21
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
Пример #22
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)