¿Cómo se escribe una etiqueta para que una escritura cortada no pase por válida?
Pon primero a cero la longitud del mensaje, escribe el mensaje, y escribe la longitud real al final. Una interrupción antes del último paso deja una etiqueta que se lee como vacía en lugar de una longitud que anuncia bytes que nunca llegaron. La pila NFC de Android escribe así en los tipos 2, 4 y 5.
Una escritura son muchos comandos
Una etiqueta de tipo 2 acepta cuatro bytes por comando. La referencia de MifareUltralight documenta writePage() como escribir una página y dice que el protocolo escribe siempre una página cada vez, así que un mensaje de cien bytes son unos veinticinco comandos. Una etiqueta que se va entre dos de ellos conserva las páginas ya escritas junto a las que contenía antes.
Lo que decide el resultado es el campo de longitud. Escrito primero con su valor nuevo, anuncia el mensaje nuevo mientras las páginas posteriores contienen todavía el viejo, y un lector analiza la mezcla como un mensaje: la página del fallo a medias describe la etiqueta que se lee entonces como corrupta o se para a la mitad. Escrito al final, no da a un lector nada que analizar hasta que el mensaje está completo.
El orden, tipo por tipo
El código abierto de la pila NFC de Android aplica los mismos tres pasos a cada tipo, y su fuente los enseña:
| Tipo | Campo de longitud | Pasos en la pila |
|---|---|---|
| Tipo 2 | La longitud del bloque TLV del NDEF | Escribe el bloque que la contiene con una longitud de cero, después el mensaje, después el bloque otra vez con la longitud real, en rw_t2t_ndef.cc |
| Tipo 4 | NLEN, al principio del archivo NDEF | Pone NLEN a 0000, escribe el mensaje detrás, y después escribe NLEN, en rw_t4t.cc |
| Tipo 5 | La longitud del bloque TLV del NDEF | Pone la longitud a cero, escribe el mensaje y el bloque Terminator, y después pone la longitud, en rw_i93.cc |
Una interrupción después del primer paso deja un mensaje NDEF de longitud cero. Los lectores declaran una etiqueta vacía, y la aplicación que la escribió puede saber que su escritura no terminó.
El orden protege el mensaje, no la página que se estaba escribiendo cuando llegó la interrupción. Lo que un chip conserva en una página cuya propia escritura se cortó es una propiedad del chip, y el orden estrecha ese riesgo a la escritura final, la que pone la longitud.
Cuando la plataforma escribe por ti
En Android, Ndef.writeNdefMessage() entrega el mensaje a la pila NFC, que lo escribe en el orden de arriba, y un código que lo usa no tiene nada que añadir salvo una relectura. Un fabricante de teléfonos puede distribuir una pila modificada, así que la relectura es la comprobación que se sostiene en todos los teléfonos.
En iOS, la referencia de Apple para writeNDEF no describe el orden que usa su escritor. Una aplicación se entera de una actualización fallida por ndefReaderSessionErrorTagUpdateFailure o una conexión perdida, como explica la página de la escritura en iOS, y vuelve a leer la etiqueta para saber qué contiene ahora.
Cuando tu código escribe las páginas
Un código que escribe páginas en bruto, para escribir una etiqueta protegida tras autenticarse o para guardar datos que no son NDEF, asume el trabajo de la pila. Para el NDEF, sigue la tabla: pon la longitud a cero, escribe el mensaje, escribe la longitud. La página que contiene la longitud suele contener también los primeros bytes del mensaje, así que la última escritura reescribe esa página con los dos, como hace la pila de Android.
Para datos que no son NDEF, la misma idea necesita un campo propio de la aplicación, una longitud, una versión o una suma de comprobación escrita detrás de los datos, que el código que lee compruebe antes de fiarse de nada. Sin él, una escritura cortada se parece exactamente a los datos.
Después vuelve a leer y compara. Una escritura cuyo último comando terminó en una excepción tiene un resultado desconocido, y la página del fallo a medias explica por qué leer va antes que cualquier reintento.
Preguntas frecuentes
¿Ndef.writeNdefMessage ya escribe en este orden?
En el código abierto de la pila NFC de Android sí, en las etiquetas de tipo 2, 4 y 5. Vuelve a leer la etiqueta de todos modos, ya que un fabricante de teléfonos puede modificar la pila.
¿Qué ve un lector tras una escritura interrumpida?
Un mensaje NDEF de longitud cero, cuando la interrupción llegó entre el primer paso y el último. Las aplicaciones lo declaran como una etiqueta vacía.
¿La escritura final de la longitud puede interrumpirse?
Sí, y ningún orden protege ese comando. El orden estrecha el riesgo a una sola escritura, y lo que contiene una página cortada durante su propia escritura depende del chip.
¿iOS escribe el NDEF en el mismo orden?
La referencia de Apple no lo dice. Comprueba el resultado volviendo a leer la etiqueta después de escribir.