divendres, 30 de juny del 2017

"Màgia" amb els bits dels WebSockets

Per un projecte que estem desenvolupant a Amidasoft, he hagut d'implementar una comunicació entre Javascript i un servidor en Java via WebSockets. La veritat és que és senzill d'implementar (com tota comunicació via Sockets amb llenguatges d'alt nivell), però hi ha una particularitat que m'ha fet perdre algunes hores: l'alineament dels primers bits del frame de resposta des del servidor.

Segons la documentació, el frame és:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len |    Extended payload length    |
|I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
|N|V|V|V|       |S|             |   (if payload len==126/127)   |
| |1|2|3|       |K|             |                               |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
|     Extended payload length continued, if payload len == 127  |
+ - - - - - - - - - - - - - - - +-------------------------------+
|                               |Masking-key, if MASK set to 1  |
+-------------------------------+-------------------------------+
| Masking-key (continued)       |          Payload Data         |
+-------------------------------- - - - - - - - - - - - - - - - +
:                     Payload Data continued ...                :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
|                     Payload Data continued ...                |
+---------------------------------------------------------------+

Això dóna a entrendre que, si estem parlant de paquets petits (menys de 128 bytes), el seu primer byte serà:
     10000001    => 0xA1
Ja que es tracta del darrer paquet i el seu opcode és 1. No sé per quina raó, amb aquest primer byte el navegador no és capaç d'interpretar bé el frame.

Al final, ho he solucionat canviant aquest byte per 0x81, tal com s'indica a l'exemple de http://bitsofgyan.com/index.php/2015/10/18/writing-a-simple-websocket-server-in-java/

No tinc clar perquè, però així funciona.