XMODEM file transfer protocol

This is a literal implementation of XMODEM.TXT, XMODEM1K.TXT and XMODMCRC.TXT, support for YMODEM and ZMODEM is pending. YMODEM should be fairly easy to implement as it is a hack on top of the XMODEM protocol using sequence bytes 0x00 for sending file names (and some meta data).

Data flow example including error recovery

Here is a sample of the data flow, sending a 3-block message. It includes the two most common line hits - a garbaged block, and an ACK reply getting garbaged. CRC or CSUM represents the checksum bytes.

XMODEM 128 byte blocks

SENDER                                      RECEIVER

                                        <-- NAK
SOH 01 FE Data[128] CSUM                -->
                                        <-- ACK
SOH 02 FD Data[128] CSUM                -->
                                        <-- ACK
SOH 03 FC Data[128] CSUM                -->
                                        <-- ACK
SOH 04 FB Data[128] CSUM                -->
                                        <-- ACK
SOH 05 FA Data[100] CPMEOF[28] CSUM     -->
                                        <-- ACK
EOT                                     -->
                                        <-- ACK

XMODEM-1k blocks, CRC mode

SENDER                                      RECEIVER

                                        <-- C
STX 01 FE Data[1024] CRC CRC            -->
                                        <-- ACK
STX 02 FD Data[1024] CRC CRC            -->
                                        <-- ACK
STX 03 FC Data[1000] CPMEOF[24] CRC CRC -->
                                        <-- ACK
EOT                                     -->
                                        <-- ACK

Mixed 1024 and 128 byte Blocks

SENDER                                      RECEIVER

                                        <-- C
STX 01 FE Data[1024] CRC CRC            -->
                                        <-- ACK
STX 02 FD Data[1024] CRC CRC            -->
                                        <-- ACK
SOH 03 FC Data[128] CRC CRC             -->
                                        <-- ACK
SOH 04 FB Data[100] CPMEOF[28] CRC CRC  -->
                                        <-- ACK
EOT                                     -->
                                        <-- ACK

YMODEM Batch Transmission Session (1 file)

SENDER                                      RECEIVER
                                        <-- C (command:rb)
SOH 00 FF foo.c NUL[123] CRC CRC        -->
                                        <-- ACK
                                        <-- C
SOH 01 FE Data[128] CRC CRC             -->
                                        <-- ACK
SOH 02 FC Data[128] CRC CRC             -->
                                        <-- ACK
SOH 03 FB Data[100] CPMEOF[28] CRC CRC  -->
                                        <-- ACK
EOT                                     -->
                                        <-- NAK
EOT                                     -->
                                        <-- ACK
                                        <-- C
SOH 00 FF NUL[128] CRC CRC              -->
                                        <-- ACK
class xmodem.XMODEM(getc, putc)

XMODEM Protocol handler, expects an object to read from and an object to write to.

>>> def getc(size, timeout=1):
...     return data or None
...
>>> def putc(data, timeout=1):
...     return size or None
...
>>> modem = XMODEM(getc, putc)
abort(count=2, timeout=60)

Send an abort sequence using CAN bytes.

calc_checksum(data, checksum=0)

Calculate the checksum for a given block of data, can also be used to update a checksum.

>>> csum = modem.calc_checksum('hello')
>>> csum = modem.calc_checksum('world', csum)
>>> hex(csum)
'0x3c'
calc_crc(data, crc=0)

Calculate the Cyclic Redundancy Check for a given block of data, can also be used to update a CRC.

>>> crc = modem.calc_crc('hello')
>>> crc = modem.calc_crc('world', crc)
>>> hex(crc)
'0xd5e3'
recv(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.

send(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.