Beispiel #1
0
    def _recv_header(self, timeout, errors=10):
        header_length = 0
        error_count = 0
        char = None
        continues_can_ch_cnt = 0
        while header_length <= 0:
            # Frist ZPAD
            while char != ZPAD:
                char = self._recv_raw(timeout)
                if char is TIMEOUT:
                    return [TIMEOUT]
                if char is ZDLE:
                    continues_can_ch_cnt += 1
                    if continues_can_ch_cnt >= 5:
                        return [ZCAN]
                else:
                    continues_can_ch_cnt = 0

            # Second ZPAD
            char = self._recv_raw(timeout)
            if char == ZPAD:
                # Get raw character
                char = self._recv_raw(timeout)
                if char is TIMEOUT:
                    return [TIMEOUT]

            # Spurious ZPAD check
            if char != ZDLE:
                continue

            # Read header style
            char = self._recv_raw(timeout)
            if char is TIMEOUT:
                return [TIMEOUT]

            if char == ZBIN:
                header_length, header = self._recv_bin16_header(timeout)
                self._recv_bits = 16
            elif char == ZHEX:
                header_length, header = self._recv_hex_header(timeout)
                self._recv_bits = 16
            elif char == ZBIN32:
                header_length, header = self._recv_bin32_header(timeout)
                self._recv_bits = 32
            else:
                error_count += 1
                if error_count > errors:
                    return [TIMEOUT]
                continue
        if header[0] != ZACK:
            log.info('GET header %d, %s' % (header_length, header))

        # We received a valid header

        return header
Beispiel #2
0
 def _send_zfile_header(self, filename, file_fize, m_time, files_to_tran,
                        left_all_file_size, timeout):
     data = []
     if not isinstance(filename, bytes):
         try:
             filename = bytes(filename, 'utf-8')
         except Exception as e:
             filename = bytes([ord(_) for _ in filename if ord(_) < 255])
     filename.replace(b'\\', b'/').replace(b'//', b'/')
     mode = 0
     trans_sn = 666
     data.append(b"%s\x00%d %d %d %d %d %d" %
                 (filename, file_fize, m_time, mode, trans_sn,
                  files_to_tran, left_all_file_size))
     data.append(b'\0')
     log.info("sendZFILE:%s" % filename)
     self._send_bin16_header([ZFILE, 0, 0, 6, 3], timeout)
     return self._write_zdle_data(ZCRCW, b''.join(data), timeout)
Beispiel #3
0
    def _recv_file(self, basedir, timeout, retry):
        log.info('Abort 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('\x00')
        filename = part[0]
        filepath = os.path.join(basedir, os.path.basename(filename))
        fp = open(filepath, 'wb')
        part = part[1].split(' ')
        log.info('Meta %r' % (part,))
        size = int(part[0])
        # Date is octal (!?)
        date = datetime.datetime.fromtimestamp(int(part[1], 8))
        # We ignore mode and serial number, whatever, dude :-)

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

        # Receive contents
        start = time.time()
        kind = None
        total_size = 0
        while total_size < size:
            kind, chunk_size = self._recv_file_data(fp.tell(), fp, timeout)
            total_size += chunk_size
            if kind == ZEOF:
                break

        # End of file
        speed = (total_size / (time.time() - start))
        log.info('Receiving file "%s" done at %.02f bps' % (filename, speed))

        # Update file metadata
        fp.close()
        mtime = time.mktime(date.timetuple())
        os.utime(filepath, (mtime, mtime))
Beispiel #4
0
    def _recv_file(self, basedir, timeout, retry):
        log.info('Abort 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('\x00')
        filename = part[0]
        filepath = os.path.join(basedir, os.path.basename(filename))
        fp = open(filepath, 'wb')
        part = part[1].split(' ')
        log.info('Meta %r' % (part, ))
        size = int(part[0])
        # Date is octal (!?)
        date = datetime.datetime.fromtimestamp(int(part[1], 8))
        # We ignore mode and serial number, whatever, dude :-)

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

        # Receive contents
        start = time.time()
        kind = None
        total_size = 0
        while total_size < size:
            kind, chunk_size = self._recv_file_data(fp.tell(), fp, timeout)
            total_size += chunk_size
            if kind == ZEOF:
                break

        # End of file
        speed = (total_size / (time.time() - start))
        log.info('Receiving file "%s" done at %.02f bps' % (filename, speed))

        # Update file metadata
        fp.close()
        mtime = time.mktime(date.timetuple())
        os.utime(filepath, (mtime, mtime))
Beispiel #5
0
    def recv(self, basedir, retry=16, timeout=60, delay=1):
        '''
        Receive some files via the ZMODEM 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.
        '''
        # Loop until we established a connection, we expect to receive a
        # different packet than ZRQINIT
        kind = TIMEOUT
        while kind in [TIMEOUT, ZRQINIT]:
            self._send_zrinit(timeout)
            kind = self._recv_header(timeout)[0]

        log.info('ZMODEM connection established')

        # Receive files
        while kind != ZFIN:
            if kind == ZFILE:
                self._recv_file(basedir, timeout, retry)
                kind = TIMEOUT
            elif kind == ZFIN:
                continue
            else:
                log.info('Did not get a file offer? Sending position header')
                self._send_pos_header(ZCOMPL, 0, timeout)
                kind = TIMEOUT

            while kind is TIMEOUT:
                self._send_zrinit(timeout)
                kind = self._recv_header(timeout)[0]

        # Acknowledge the ZFIN
        log.info('Received ZFIN, done receiving files')
        self._send_hex_header([ZFIN, 0, 0, 0, 0], timeout)

        # Wait for the over and out sequence
        while kind not in [ord('O'), TIMEOUT]:
            kind = self._recv(timeout)

        if kind is not TIMEOUT:
            while kind not in [ord('O'), TIMEOUT]:
                kind = self._recv(timeout)
Beispiel #6
0
    def recv(self, basedir, retry=16, timeout=60, delay=1):
        '''
        Receive some files via the ZMODEM 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.
        '''
        # Loop until we established a connection, we expect to receive a
        # different packet than ZRQINIT
        kind = TIMEOUT
        while kind in [TIMEOUT, ZRQINIT]:
            self._send_zrinit(timeout)
            kind = self._recv_header(timeout)[0]

        log.info('ZMODEM connection established')

        # Receive files
        while kind != ZFIN:
            if kind == ZFILE:
                self._recv_file(basedir, timeout, retry)
                kind = TIMEOUT
            elif kind == ZFIN:
                continue
            else:
                log.info('Did not get a file offer? Sending position header')
                self._send_pos_header(ZCOMPL, 0, timeout)
                kind = TIMEOUT

            while kind is TIMEOUT:
                self._send_zrinit(timeout)
                kind = self._recv_header(timeout)[0]

        # Acknowledge the ZFIN
        log.info('Received ZFIN, done receiving files')
        self._send_hex_header([ZFIN, 0, 0, 0, 0], timeout)

        # Wait for the over and out sequence
        while kind not in [ord('O'), TIMEOUT]:
            kind = self._recv(timeout)

        if kind is not TIMEOUT:
            while kind not in [ord('O'), TIMEOUT]:
                kind = self._recv(timeout)
Beispiel #7
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)
Beispiel #8
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
Beispiel #9
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)