No hace mucho comentaba que me había puesto a partir paquetes IP a bajo nivel, usando JPcap. Haciéndolo encontré un pequeño bug en la librería, el campo offset de la cabecera IP no se rellenaba correctamente, por lo que tuve que hacerme mi pequeño arreglo. Una vez hecho, todos felices y contentos.
Pero me ha salido un nuevo problema. Cuando el sistema operativo recibe los fragmentos IP de un paquete grande, tiene un pequeño timeout en el que espera recibir todos esos paquetes (creo que de 1 minuto aproximadamente). Si en 1 minuto no recibe todos los fragmentos, desecha el paquete y no lo entrega a las aplicaciones. En windows ese timeout se controla ¿cómo no?, con un valor del registro, en concreto IpReassemblyTimeout. Pero mira tú que 1 minuto me resulta escaso (tenemos un canal de comunicación muy lento, casi como un antiguo RS-232 de 9600 baudios y encima compartido) y no todas las versiones de windows hacen caso de ese valor de registro (casualmente la que nosotros usamos no lo hace).
Así que me toca reconstruir también los fragmentos con JPcap. Y me pongo a ello…. y encuentro un nuevo bug. Hay un flag en la cabecera IP que indica si ese fragmento es el último o hay más. Pues bien, JPcap no rellena bien en recepción ese flag ni los otros dos flags que le acompañan. Poniendo el arreglo del enlace ya se arregla el tema de los flags. Pero me sale un nuevo problema … no recibo el último fragmento … hasta que llega un mensaje. Es como si JPcap se quedara el último paquete recibido y no lo entregara a la aplicación hasta que reciba uno nuevo. No sé si es eso, pero el caso es que si sólo envio un gran paquete UDP fragmentado, no recibo el último fragmento y no puedo recomponer el paquete UDP.
Así que me pongo a buscar alternativas a JPcap y me encuentro con JNetPcap. Con esta librería sólo he probado la reconstrucción de paquetes, pero me ha funcionado bien a la primera (o casi). La librería es un pelín más compleja de usar que JPcap, pero viene bastante mejor documentada en su página web, con más ejemplos y lo más importante, parece que funciona mejor.
De momento no voy a migrar el envío de fragmentos, pero creo que sí voy a reconstruirlos con esta librería, afortunadamente, ambas son compatibles y una misma aplicación puede usarlas simultáneamente.
¿Es posible que se te quede en espera porque estés leyendo más datos de entrada de los que contiene el último paquete?
A mí alguna vez al hacer el read del inputstream se me ha quedado «muerto» así, hasta que termina de recibir los datos y entonces ya empieza a trabajar…
No sé cómo trabaja por dentro jpcap. Yo le añado a la clase correspondiente de jpcap un «listener» y ella me avisa cuando llega un paquete ya construido, un IPPacket, UDPPacekt o lo que sea con su array de byte[] de datos y métodos para obtener los campos de la cabecera correspondiente.
Veo de todas formas que jpcap lleva parado mucho tiempo en su versión 0.7 (la que yo estoy usando), pero veo también que hay dos versiones, una en http://jpcap.sourceforge.net/ y la otra en http://netresearch.ics.uci.edu/kfujii/Jpcap/doc/ Quizás una vaya mejor que la otra.