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
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)
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))
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))
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)
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)
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
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)