2012-02-07 3 views
6

Tôi đang cố gắng giải mã khung websocket, nhưng tôi không thành công khi giải mã tải trọng mở rộng. Dưới đây là những gì tôi đã đạt được cho đến thời điểm này:Giải mã khung websocket

char *in = data; 
char *buffer; 
unsigned int i; 
unsigned char mask[4]; 
unsigned int packet_length = 0; 
int rc; 

/* Expect a finished text frame. */ 
assert(in[0] == '\x81'); 
packet_length = ((unsigned char) in[1]) & 0x7f; 

mask[0] = in[2]; 
mask[1] = in[3]; 
mask[2] = in[4]; 
mask[3] = in[5]; 

if (packet_length <= 125) {   **// This decoding works** 
    /* Unmask the payload. */ 
    for (i = 0; i < packet_length; i++) 
     in[6 + i] ^= mask[i % 4]; 
    rc = asprintf(&buffer, "%.*s", packet_length, in + 6); 
} else 
    if (packet_length == 126) {  **//This decosing does NOT work** 
     /* Unmask the payload. */ 
     for (i = 0; i < packet_length; i++) 
      in[8 + i] ^= mask[i % 4]; 
     rc = asprintf(&buffer, "%.*s", packet_length, in + 8); 
} 

Tôi đang làm gì sai? Làm cách nào để mã hóa tải trọng mở rộng?

Trả lời

5

Nếu packet_length là 126, 2 byte sau cho biết thời lượng đọc dữ liệu.
Nếu packet_length là 127, 8 byte sau cho độ dài dữ liệu cần đọc.
Mặt nạ được chứa trong 4 byte sau (sau độ dài).
Thông báo được giải mã sau này.

data framing section thông số kỹ thuật có minh họa hữu ích về điều này.

Nếu bạn xếp lại thứ tự mã của bạn để một cái gì đó giống như

  • đọc packet_length
  • Kiểm tra packet_length của 126 hoặc 127. phân công lại packet_length để giá trị của sau 2/4 byte nếu cần thiết.
  • Đọc mặt nạ (4 byte sau packet_length, bao gồm bất kỳ 2 hoặc 8 byte bổ sung nào đọc cho bước trên).
  • Thông báo giải mã (mọi thứ sau mặt nạ).

thì mọi thứ sẽ hoạt động.

+0

thực hiện một sửa đổi nhỏ: 127 trong chiều dài có nghĩa là 8 byte sau đây giữ chiều dài tải trọng (không phải 4) – kanaka

+1

@kanaka oops, cảm ơn vì đã phát hiện ra rằng – simonc

4

Điểm gắn bó ở mức> 125 byte tải trọng.

Cấu trúc của nó khá đơn giản, cho phép nói bạn gửi mười một trong JavaScript:

ws.send("a".repeat(10)) 

Sau đó máy chủ sẽ nhận được:

bytes[16]=818a8258a610e339c771e339c771e339 
  • byte 0: Các 0x81 chỉ là một chỉ báo rằng một tin nhắn đã nhận được
  • byte 1: 0x8a là độ dài, trừ 80 từ nó, 0x0A == 10
  • byte 2, 3, 4, 5: 4 byte trọng xor để giải mã payload
  • phần còn lại: tải trọng

Nhưng bây giờ cho phép nói rằng bạn gửi 126 của một trong JavaScript:

ws.send("a".repeat(126)) 

sau đó máy chủ sẽ nhận được:

bytes[134]=81fe007ee415f1e5857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574 

Nếu chiều dài của payload là> 125, byte 1 sẽ có 0xFE giá trị, thay đổi định dạng sau đó đến:

  • byte 0: Các 0x81 chỉ là một chỉ báo rằng một tin nhắn đã nhận
  • byte 1: sẽ 0xFE
  • byte 2, 3: chiều dài của tải trọng như một số uint16
  • byte 4, 5, 6, 7: 4 byte chìa khóa để giải mã xor payload
  • phần còn lại: tải trọng đang

Ví dụ trong C#:

List<byte[]> decodeWebsocketFrame(Byte[] bytes) 
{ 
    List<Byte[]> ret = new List<Byte[]>(); 
    int offset = 0; 
    while (offset + 6 < bytes.Length) 
    { 
     // format: 0==ascii/binary 1=length-0x80, byte 2,3,4,5=key, 6+len=message, repeat with offset for next... 
     int len = bytes[offset + 1] - 0x80; 

     if (len <= 125) 
     { 

      //String data = Encoding.UTF8.GetString(bytes); 
      //Debug.Log("len=" + len + "bytes[" + bytes.Length + "]=" + ByteArrayToString(bytes) + " data[" + data.Length + "]=" + data); 
      Debug.Log("len=" + len + " offset=" + offset); 
      Byte[] key = new Byte[] { bytes[offset + 2], bytes[offset + 3], bytes[offset + 4], bytes[offset + 5] }; 
      Byte[] decoded = new Byte[len]; 
      for (int i = 0; i < len; i++) 
      { 
       int realPos = offset + 6 + i; 
       decoded[i] = (Byte)(bytes[realPos]^key[i % 4]); 
      } 
      offset += 6 + len; 
      ret.Add(decoded); 
     } else 
     { 
      int a = bytes[offset + 2]; 
      int b = bytes[offset + 3]; 
      len = (a << 8) + b; 
      //Debug.Log("Length of ws: " + len); 

      Byte[] key = new Byte[] { bytes[offset + 4], bytes[offset + 5], bytes[offset + 6], bytes[offset + 7] }; 
      Byte[] decoded = new Byte[len]; 
      for (int i = 0; i < len; i++) 
      { 
       int realPos = offset + 8 + i; 
       decoded[i] = (Byte)(bytes[realPos]^key[i % 4]); 
      } 

      offset += 8 + len; 
      ret.Add(decoded); 
     } 
    } 
    return ret; 
}