2012-03-07 32 views
9

Necesito incluir rutinas básicas de envío de archivos y recepción de archivos en mi programa, y ​​debe ser a través del protocolo ZMODEM. El problema es que estoy teniendo problemas para entender la especificación.Comprensión del protocolo ZMODEM

Como referencia, here is the specification.

La especificación no define las distintas constantes, por lo que aquí está a header file from Google.

Me parece que hay un montón de cosas importantes que deja sin definir en ese documento:

  • Se refiere constantemente a ZDLE-codificación, pero ¿qué es? ¿Cuándo exactamente lo uso y cuándo no lo uso?
  • Después de una trama de datos ZFILE, se transfieren los metadatos del archivo (nombre de archivo, fecha de modificación, tamaño, etc.). Esto es seguido por un bloque ZCRCW y luego un bloque cuyo tipo no está definido de acuerdo con la especificación. El bloque ZCRCW supuestamente contiene un CRC de 16 bits, pero la especificación no define en qué datos se calcula el CRC.
  • No define el polinomio CRC que utiliza. Descubrí por casualidad que el CRC32 poly es el CRC32 estándar, pero no he tenido tanta suerte con el CRC16 poly. No importa, lo encontré por prueba y error. El CRC16 poly es 0x1021.

He buscado el código de referencia, pero todo lo que puedo encontrar son archivos C ilegibles e indocumentados de principios de los 90. También he encontrado este conjunto de documentos de la MSDN, pero es dolorosamente vago y contradictorio a pruebas que me he encontrado: http://msdn.microsoft.com/en-us/library/ms817878.aspx (puede que tenga que ver que a través de Google's cache)

Para ilustrar mis dificultades, aquí es una ejemplo simple He creado un archivo de texto plano en el servidor que contiene "Hello world!", Y se llama helloworld.txt.

que iniciar la transferencia desde el servidor con el siguiente comando:

sx --zmodem helloworld.txt 

Esto indica al servidor para enviar la trama siguiente ZRQINIT:

2A 2A 18 42 30 30 30 30 30 30 30 30 30 30 30 30 **.B000000000000 
30 30 0D 8A 11         00.Š. 

Tres problemas con esto:

  • ¿Los bytes de relleno (0x2A) son arbitrarios? ¿Por qué hay dos aquí, pero en otros casos solo hay uno, y a veces ninguno?
  • La especificación no menciona [CR] [LF] [XON] al final, pero sí el artículo de MSDN. ¿Por qué está ahí?
  • ¿Por qué [LF] tiene el bit 0x80 establecido?

Después de esto, el cliente debe enviar un marco ZRINIT. Tengo este del artículo de MSDN:

2A 2A 18 42 30 31 30 30 30 30 30 30 32 33 62 65 **.B0100000023be 
35 30 0D 8A          50.Š 

Además de la cuestión de la bandera 0x80 [LF], tengo dos cuestiones más:

  • ¿Por qué no se [XON] incluidos en esta ocasión?
  • ¿Se calcula el CRC en los datos binarios o en los datos hexadecimales ASCII? Si está en los datos binarios obtengo 0x197C, y si está en los datos hexadecimales ASCII obtengo 0xF775; ninguno de estos es lo que está realmente en el cuadro (0xBE50). (Resuelto, sigue el modo que esté utilizando. Si está en modo BIN o BIN32, es el CRC de los datos binarios. Si está en modo hexadecimal ASCII, es el CRC de lo que representa el hex ASCII caracteres)

El servidor responde con un marco zfile:.

2A 18 43 04 00 00 00 00 DD 51 A2 33    *.C.....ÝQ¢3 

OK. Esto tiene sentido. Si calculo el CRC32 de [04 00 00 00 00], de hecho obtengo 0x33A251DD. Pero ahora no tenemos CUALQUIER [CR] [LF] [XON] al final. ¿Por qué es esto?

Inmediatamente después de este marco, el servidor envía también los metadatos del archivo:

68 65 6C 6C 6F 77 6F 72 6C 64 2E 74 78 74 00 31 helloworld.txt.1 
33 20 32 34 30 20 31 30 30 36 34 34 20 30 20 31 3 240 100644 0 1 
20 31 33 00 18 6B 18 50 D3 0F F1 11    13..k.PÓ.ñ. 

Esto no tiene ni siquiera una cabecera, sólo se salta directamente a los datos. OK, puedo vivir con eso. Sin embargo:

  • Tenemos nuestro primer marco ZCRCW misterioso: [18 6B]. ¿Cuánto dura este marco? ¿Dónde están los datos CRC, y es CRC16 o CRC32? No está definido en ninguna parte de la especificación.
  • El artículo de MSDN especifica que [18 6B] debe ir seguido de [00], pero no lo es.
  • Luego tenemos un marco con un tipo indefinido: [18 50 D3 0F F1 11]. ¿Es este un marco separado o es parte de ZCRCW?

El cliente debe responder con un marco ZRPOS, de nuevo tomado del artículo de MSDN:

2A 2A 18 42 30 39 30 30 30 30 30 30 30 30 61 38 **.B0900000000a8 
37 63 0D 8A          7c.Š 

mismos problemas que con el marco ZRINIT: el CRC es incorrecto, el [LF] tiene bit 0x80 establecido, y no hay [XON].

el servidor responde con un marco ZDATA:

2A 18 43 0A 00 00 00 00 BC EF 92 8C    *.C.....¼ï’Œ 

mismos problemas que zfile: la CDN es todo muy bien, pero ¿dónde está el [CR] [LF] [XON]?

Después de esto, el servidor envía la carga del archivo. Dado que este es un ejemplo corto, cabe en un bloque (tamaño máximo es de 1024):

48 65 6C 6C 6F 20 77 6F 72 6C 64 21 0A   Hello world!. 

De lo que el artículo parece mencionar, cargas útiles se escapó con [ZDLE]. Entonces, ¿cómo puedo transmitir un byte de carga que coincide con el valor de [ZDLE]? ¿Hay otros valores como este?

El servidor termina con estos marcos:

18 68 05 DE 02 18 D0        .h.Þ..Ð 
2A 18 43 0B 0D 00 00 00 D1 1E 98 43    *.C.....Ñ.˜C 

estoy completamente perdido en la primera. El segundo tiene tanto sentido como los marcos ZRINIT y ZDATA.

+0

Estoy trabajando exactamente de la misma manera precisamente por la misma razón; Si alguna vez hiciste esto, y tienes un código fuente, sería increíble ... –

+0

¿Cómo terminó esto? Después de pasar unos días codificando para que ZMODEM recibiera el trabajo confiable, me di por vencido y simplemente le pedí a lrz. Trabajó en un día. No está ni cerca como limpio, pero realmente no tenía ganas de pasar más tiempo en un protocolo venerable pero obsoleto ... – bronson

+0

Además, ¡cuidado! ¡Encontré algunas otras bibliotecas de código de zmodem pero eran completamente poco confiables! Probablemente el 5% de los archivos que probé terminaron en fracaso, y ni siquiera estaba tratando de explotar los casos de las esquinas. Asegúrate de usar código probado en batalla, no el proyecto de fin de semana de alguien. – bronson

Respuesta

6

Mi amigo se pregunta si está implementando una máquina de tiempo .

No sé que puedo responder todas sus preguntas - Nunca me he hecho, tuvimos que aplicar zmodem mí - pero aquí están algunas respuestas:

De lo que el artículo parece mencionar, las cargas útiles se escapan con [ZDLE]. Entonces, ¿cómo puedo transmitir un byte de carga que coincide con el valor de [ZDLE]? ¿Hay otros valores como este?

Esto se aborda explícitamente en el documento se ha vinculado a la comienzo de sus preguntas, que dice:

The ZDLE character is special. ZDLE represents a control sequence 
of some sort. If a ZDLE character appears in binary data, it is 
prefixed with ZDLE, then sent as ZDLEE. 

Se refiere constantemente a ZDLE-codificación, pero ¿qué es? Cuando exactamente lo uso, ¿y cuándo no lo uso?

En los días de antigüedad, ciertos "caracteres de control" se utilizaron para controlar el canal comunicación (de ahí el nombre). Por ejemplo, el envío de caracteres XON/XOFF puede detener la transmisión. ZDLE se usa para escapar de los caracteres que pueden ser problemáticos. De acuerdo con la especificación, estos son los caracteres que se escaparon por defecto:

ZMODEM software escapes ZDLE, 020, 0220, 021, 0221, 023, and 0223. 
If preceded by 0100 or 0300 (@), 015 and 0215 are also escaped to 
protect the Telenet command escape [email protected] The receiver ignores 
021, 0221, 023, and 0223 characters in the data stream. 

que he mirado alrededor de código de referencia, pero todo lo que puedo encontrar son ilegibles, indocumentados archivos de C a partir de los años 90 .

¿Esto incluye el código para el paquete lrzsz? Esto sigue siendo ampliamente disponible en la mayoría de las distribuciones de Linux (y sorprendentemente útil para transmitir archivos a través de una conexión ssh establecida).

Hay una serie de otras implementaciones por ahí, incluyendo varios en software que se enumera en freecode, incluyendo qodem, syncterm, MBSE, y otros. Creo que el syncterm implementation está escrito como una biblioteca que puede ser razonablemente fácil para usar desde su propio código (pero no estoy seguro).

Puede encontrar un código adicional si examina las colecciones más antiguas del software MS-DOS .

+0

Estamos utilizando algunas placas de desarrollo en el trabajo que ejecutan una imagen personalizada de Linux, y la única forma de comunicarse con ellas es a través del puerto UART (COM1). Con frecuencia tenemos que editar archivos en la compilación (usando un programa envoltorio en el que estoy trabajando), así que en lugar de compilar una nueva imagen cada vez, optamos por lrzsz. El personaje que escapa es un poco más claro ahora, pero todavía me pregunto cuál es el alcance. Gracias por los enlaces de código, debería ayudar a descubrir estos matices. Voy a marcar esto como la respuesta por ahora. –

1

No puedo culparte. El manual de usuario no está organizado de manera fácil de usar

¿Los bytes de relleno (0x2A) son arbitrarios?

No, de la página 14,15:

Un encabezado binario comienza con la secuencia ZPAD, ZDLE, ZBIN.

Un encabezado hexadecimal comienza con la secuencia ZPAD, ZPAD, ZDLE, ZHEX.

.

La especificación no menciona el [CR] [LF] [XON] al final, pero sí el artículo de MSDN. ¿Por qué está ahí?

Página 15

* * ZDLE B TIPO F3/F2 P0/P1 F1/F0 P2/P3 CRC CRC-1-2 CR LF XON . ¿Por qué [LF] tiene el bit 0x80 establecido?

No estoy seguro. Del término de Tera obtuve ambos caracteres de control XORed con 0x80 (8D 8A 11)

Tenemos nuestro primer marco misterioso ZCRCW: [18 6B]. ¿Cuánto dura este marco? ¿Dónde están los datos CRC, y es CRC16 o CRC32? No está definido en ninguna parte de la especificación.

El ZCRCW no es un encabezado o un tipo de marco, es más como un pie de página que le dice al receptor qué esperar a continuación. En este caso, es el pie de página del subpaquete de datos que contiene el nombre del archivo. Va a ser una suma de comprobación de 32 bits porque está usando un encabezado binario de tipo "C".

  • ZDLE C TIPO F3/P0 F2/F1 P1/P2 F0/P3 CRC-1 CRC-2 CRC-3 CRC-4

.

Luego tenemos un marco con un tipo indefinido: [18 50 D3 0F F1 11]. ¿Es este un marco separado o es parte de ZCRCW?

Ese es el CRC para el subpaquete de datos ZCRCW. Son 5 bytes porque el primero es 0x10, un personaje de control que necesita ser escapado ZDLE. No estoy seguro de qué es 0x11.

y no hay [XON].

XON es solo para encabezados hexadecimales. No lo usa para un encabezado binario.

  • ZDLE A TIPO F3/P0 F2/F1 P1/P2 F0/P3 CRC-1 CRC-2 . Entonces, ¿cómo puedo transmitir un byte de carga útil que coincide con el valor de [ZDLE]?

18 58 (También conocido como ZDLEE)

18 68 05 02 18 DE D0

Ese es el pie de página de la subtrama de datos.Los siguientes 5 bytes son el CRC (el último byte está codificado en ZDLE)

Cuestiones relacionadas