解码 websocket 框架

发布于 2025-01-03 13:36:31 字数 911 浏览 1 评论 0原文

我正在尝试解码 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);
}

我做错了什么?如何对扩展有效负载进行编码?

I am trying to decode a websocket frame, but I'm not successful when it comes to decoding the extended payload. Here what I did achieve so far:

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);
}

What am I doing wrong? How do I encode the extended payload?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

那片花海 2025-01-10 13:36:31

症结点在于>。 125 字节有效负载。

格式非常简单,假设您在 JavaScript 中发送十个 a:

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

然后服务器将收到:

bytes[16]=818a8258a610e339c771e339c771e339
  • 字节 0:0x81 只是消息接收的指示符
  • 字节 1:0x8a 是长度,从中减去 0x80,0x0A = = 10
  • 字节 2, 3, 4, 5:用于解密有效负载的 4 字节异或密钥
  • 其余:有效负载

但现在假设您发送 126 个 a在JavaScript中:

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

那么服务器将收到:

bytes[134]=81fe007ee415f1e5857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574

如果有效负载的长度> 125,字节 1 的值为 0xfe,格式随后更改为:

  • 字节 0:0x81 只是一个指示符,表明收到的消息
  • 字节 1:将是 0xfe
  • 字节 2、3:作为 uint16 数字的有效负载的长度
  • 字节 4, 5, 6, 7:用于解密有效负载的 4 字节异或密钥
  • 其余部分:有效负载

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;
}

The sticking point is at > 125 bytes payload.

The format is pretty simple, lets say you send ten a's in JavaScript:

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

Then the server will receive:

bytes[16]=818a8258a610e339c771e339c771e339
  • byte 0: The 0x81 is just an indicator that a message received
  • byte 1: the 0x8a is the length, substract 0x80 from it, 0x0A == 10
  • byte 2, 3, 4, 5: the 4 byte xor key to decrypt the payload
  • the rest: payload

But now lets say you send 126 a's in JavaScript:

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

Then the server will receive:

bytes[134]=81fe007ee415f1e5857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574908485749084857490848574

If the length of the payload is > 125, the byte 1 will have the value 0xfe, the format changes then to:

  • byte 0: The 0x81 is just an indicator that a message received
  • byte 1: will be 0xfe
  • byte 2, 3: the length of the payload as a uint16 number
  • byte 4, 5, 6, 7: the 4 byte xor key to decrypt the payload
  • the rest: payload

Example code in 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;
}
时光暖心i 2025-01-10 13:36:31

如果packet_length为126,则接下来的2个字节给出要读取的数据的长度。

如果packet_length为127,则接下来的8个字节给出了要读取的数据的长度。

掩码包含在以下 4 个字节中(长度之后)。

要解码的消息如下。

数据框架部分规范对此有一个有用的说明。

如果您将代码重新排序为

  • “读取 packet_length”
  • 之类的内容,请检查 packet_length 是否为 126 或 127。如果需要,请将 packet_length 重新分配为以下 2/4 字节的值。
  • 读取掩码(packet_length 之后的 4 个字节,包括为上述步骤读取的任何附加 2 或 8 个字节)。
  • 解码消息(掩码后的所有内容)。

那么事情就应该可以了。

If packet_length is 126, the following 2 bytes give the length of data to be read.

If packet_length is 127, the following 8 bytes give the length of data to be read.

The mask is contained in the following 4 bytes (after the length).

The message to be decoded follows this.

The data framing section of the spec has a useful illustration of this.

If you re-order your code to something like

  • Read packet_length
  • Check for packet_length of 126 or 127. Reassign packet_length to value of following 2/4 bytes if required.
  • Read mask (the 4 bytes after packet_length, including any additional 2 or 8 bytes read for the step above).
  • Decode message (everything after the mask).

then things should work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文