コード例 #1
0
        /// <summary>
        /// Prepare WebSocket send frame
        /// </summary>
        /// <param name="buffer">Buffer to send</param>
        /// <param name="offset">Buffer offset</param>
        /// <param name="size">Buffer size</param>
        public void PrepareReceiveFrame(byte[] buffer, int offset, int size)
        {
            lock (WsReceiveLock)
            {
                var index = 0;

                // Clear received data after WebSocket frame was processed
                if (WsFrameReceived)
                {
                    WsFrameReceived = false;
                    WsHeaderSize    = 0;
                    WsPayloadSize   = 0;
                    WsReceiveFrameBuffer.Clear();
                    Array.Clear(WsReceiveMask, 0, WsReceiveMask.Length);
                }
                if (WsFinalReceived)
                {
                    WsFinalReceived = false;
                    WsReceiveFinalBuffer.Clear();
                }

                while (size > 0)
                {
                    // Clear received data after WebSocket frame was processed
                    if (WsFrameReceived)
                    {
                        WsFrameReceived = false;
                        WsHeaderSize    = 0;
                        WsPayloadSize   = 0;
                        WsReceiveFrameBuffer.Clear();
                        Array.Clear(WsReceiveMask, 0, WsReceiveMask.Length);
                    }
                    if (WsFinalReceived)
                    {
                        WsFinalReceived = false;
                        WsReceiveFinalBuffer.Clear();
                    }

                    // Prepare WebSocket frame opcode and mask flag
                    if (WsReceiveFrameBuffer.Count < 2)
                    {
                        for (int i = 0; i < 2; i++, index++, size--)
                        {
                            if (size == 0)
                            {
                                return;
                            }
                            WsReceiveFrameBuffer.Add(buffer[offset + index]);
                        }
                    }

                    byte opcode  = (byte)(WsReceiveFrameBuffer[0] & 0x0F);
                    bool fin     = ((WsReceiveFrameBuffer[0] >> 7) & 0x01) != 0;
                    bool mask    = ((WsReceiveFrameBuffer[1] >> 7) & 0x01) != 0;
                    int  payload = WsReceiveFrameBuffer[1] & (~0x80);

                    // Prepare WebSocket opcode
                    WsOpcode = (opcode != 0) ? opcode : WsOpcode;

                    // Prepare WebSocket frame size
                    if (payload <= 125)
                    {
                        WsHeaderSize  = 2 + (mask ? 4 : 0);
                        WsPayloadSize = payload;
                    }
                    else if (payload == 126)
                    {
                        if (WsReceiveFrameBuffer.Count < 4)
                        {
                            for (int i = 0; i < 2; i++, index++, size--)
                            {
                                if (size == 0)
                                {
                                    return;
                                }
                                WsReceiveFrameBuffer.Add(buffer[offset + index]);
                            }
                        }

                        payload       = ((WsReceiveFrameBuffer[2] << 8) | (WsReceiveFrameBuffer[3] << 0));
                        WsHeaderSize  = 4 + (mask ? 4 : 0);
                        WsPayloadSize = payload;
                    }
                    else if (payload == 127)
                    {
                        if (WsReceiveFrameBuffer.Count < 10)
                        {
                            for (int i = 0; i < 8; i++, index++, size--)
                            {
                                if (size == 0)
                                {
                                    return;
                                }
                                WsReceiveFrameBuffer.Add(buffer[offset + index]);
                            }
                        }

                        payload       = ((WsReceiveFrameBuffer[2] << 56) | (WsReceiveFrameBuffer[3] << 48) | (WsReceiveFrameBuffer[4] << 40) | (WsReceiveFrameBuffer[5] << 32) | (WsReceiveFrameBuffer[6] << 24) | (WsReceiveFrameBuffer[7] << 16) | (WsReceiveFrameBuffer[8] << 8) | (WsReceiveFrameBuffer[9] << 0));
                        WsHeaderSize  = 10 + (mask ? 4 : 0);
                        WsPayloadSize = payload;
                    }

                    // Prepare WebSocket frame mask
                    if (mask)
                    {
                        if (WsReceiveFrameBuffer.Count < WsHeaderSize)
                        {
                            for (int i = 0; i < 4; i++, index++, size--)
                            {
                                if (size == 0)
                                {
                                    return;
                                }
                                WsReceiveFrameBuffer.Add(buffer[offset + index]);
                                WsReceiveMask[i] = buffer[offset + index];
                            }
                        }
                    }

                    int total  = WsHeaderSize + WsPayloadSize;
                    int length = Math.Min(total - WsReceiveFrameBuffer.Count, size);

                    // Prepare WebSocket frame payload
                    WsReceiveFrameBuffer.AddRange(buffer.Skip(offset + index).Take(length));
                    index += length;
                    size  -= length;

                    // Process WebSocket frame
                    if (WsReceiveFrameBuffer.Count == total)
                    {
                        // Unmask WebSocket frame content
                        if (mask)
                        {
                            for (int i = 0; i < WsPayloadSize; i++)
                            {
                                WsReceiveFinalBuffer.Add((byte)(WsReceiveFrameBuffer[WsHeaderSize + i] ^ WsReceiveMask[i % 4]));
                            }
                        }
                        else
                        {
                            WsReceiveFinalBuffer.AddRange(WsReceiveFrameBuffer.GetRange(WsHeaderSize, WsPayloadSize));
                        }

                        WsFrameReceived = true;

                        // Finalize WebSocket frame
                        if (fin)
                        {
                            WsFinalReceived = true;

                            switch (WsOpcode)
                            {
                            case WS_PING:
                            {
                                // Call the WebSocket ping handler
                                _wsHandler.OnWsPing(WsReceiveFinalBuffer.ToArray(), 0, WsReceiveFinalBuffer.Count);
                                break;
                            }

                            case WS_PONG:
                            {
                                // Call the WebSocket pong handler
                                _wsHandler.OnWsPong(WsReceiveFinalBuffer.ToArray(), 0, WsReceiveFinalBuffer.Count);
                                break;
                            }

                            case WS_CLOSE:
                            {
                                // Call the WebSocket close handler
                                _wsHandler.OnWsClose(WsReceiveFinalBuffer.ToArray(), 0, WsReceiveFinalBuffer.Count);
                                break;
                            }

                            case WS_BINARY:
                            case WS_TEXT:
                            {
                                // Call the WebSocket received handler
                                _wsHandler.OnWsReceived(WsReceiveFinalBuffer.ToArray(), 0, WsReceiveFinalBuffer.Count);
                                break;
                            }
                            }
                        }
                    }
                }
            }
        }
コード例 #2
0
        /// <summary>
        /// Prepare WebSocket send frame
        /// </summary>
        /// <param name="buffer">Buffer to send</param>
        /// <param name="offset">Buffer offset</param>
        /// <param name="size">Buffer size</param>
        public void PrepareReceiveFrame(byte[] buffer, long offset, long size)
        {
            lock (WsReceiveLock)
            {
                var index = 0;

                // Clear received data after WebSocket frame was processed
                if (WsReceived)
                {
                    WsReceived    = false;
                    WsHeaderSize  = 0;
                    WsPayloadSize = 0;
                    WsReceiveBuffer.Clear();
                    Array.Clear(WsReceiveMask, 0, WsReceiveMask.Length);
                }

                while (size > 0)
                {
                    // Clear received data after WebSocket frame was processed
                    if (WsReceived)
                    {
                        WsReceived    = false;
                        WsHeaderSize  = 0;
                        WsPayloadSize = 0;
                        WsReceiveBuffer.Clear();
                        Array.Clear(WsReceiveMask, 0, WsReceiveMask.Length);
                    }

                    // Prepare WebSocket frame opcode and mask flag
                    if (WsReceiveBuffer.Count < 2)
                    {
                        for (int i = 0; i < 2; ++i, ++index, --size)
                        {
                            if (size == 0)
                            {
                                return;
                            }
                            WsReceiveBuffer.Add(buffer[offset + index]);
                        }
                    }

                    byte opcode  = (byte)(WsReceiveBuffer[0] & 0x0F);
                    bool fin     = ((WsReceiveBuffer[0] >> 7) & 0x01) != 0;
                    bool mask    = ((WsReceiveBuffer[1] >> 7) & 0x01) != 0;
                    int  payload = WsReceiveBuffer[1] & (~0x80);

                    // Prepare WebSocket frame size
                    if (payload <= 125)
                    {
                        WsHeaderSize             = 2 + (mask ? 4 : 0);
                        WsPayloadSize            = payload;
                        WsReceiveBuffer.Capacity = WsHeaderSize + WsPayloadSize;
                    }
                    else if (payload == 126)
                    {
                        if (WsReceiveBuffer.Count < 4)
                        {
                            for (int i = 0; i < 2; ++i, ++index, --size)
                            {
                                if (size == 0)
                                {
                                    return;
                                }
                                WsReceiveBuffer.Add(buffer[offset + index]);
                            }
                        }

                        payload                  = ((WsReceiveBuffer[2] << 8) | (WsReceiveBuffer[3] << 0));
                        WsHeaderSize             = 4 + (mask ? 4 : 0);
                        WsPayloadSize            = payload;
                        WsReceiveBuffer.Capacity = WsHeaderSize + WsPayloadSize;
                    }
                    else if (payload == 127)
                    {
                        if (WsReceiveBuffer.Count < 10)
                        {
                            for (int i = 0; i < 8; ++i, ++index, --size)
                            {
                                if (size == 0)
                                {
                                    return;
                                }
                                WsReceiveBuffer.Add(buffer[offset + index]);
                            }
                        }

                        payload                  = ((WsReceiveBuffer[2] << 56) | (WsReceiveBuffer[3] << 48) | (WsReceiveBuffer[4] << 40) | (WsReceiveBuffer[5] << 32) | (WsReceiveBuffer[6] << 24) | (WsReceiveBuffer[7] << 16) | (WsReceiveBuffer[8] << 8) | (WsReceiveBuffer[9] << 0));
                        WsHeaderSize             = 10 + (mask ? 4 : 0);
                        WsPayloadSize            = payload;
                        WsReceiveBuffer.Capacity = WsHeaderSize + WsPayloadSize;
                    }

                    // Prepare WebSocket frame mask
                    if (mask)
                    {
                        if (WsReceiveBuffer.Count < WsHeaderSize)
                        {
                            for (int i = 0; i < 4; ++i, ++index, --size)
                            {
                                if (size == 0)
                                {
                                    return;
                                }
                                WsReceiveBuffer.Add(buffer[offset + index]);
                                WsReceiveMask[i] = buffer[offset + index];
                            }
                        }
                    }

                    int total  = WsHeaderSize + WsPayloadSize;
                    int length = Math.Min(total - WsReceiveBuffer.Count, (int)size);

                    // Prepare WebSocket frame payload
                    WsReceiveBuffer.AddRange(buffer.Skip(((int)offset + index)).Take(((int)length)));
                    index += length;
                    size  -= length;

                    // Process WebSocket frame
                    if (WsReceiveBuffer.Count == total)
                    {
                        int bufferOffset = WsHeaderSize;

                        // Unmask WebSocket frame content
                        if (mask)
                        {
                            for (int i = 0; i < WsPayloadSize; ++i)
                            {
                                WsReceiveBuffer[bufferOffset + i] ^= WsReceiveMask[i % 4];
                            }
                        }

                        WsReceived = true;

                        if ((opcode & WS_PING) == WS_PING)
                        {
                            // Call the WebSocket ping handler
                            _wsHandler.OnWsPing(WsReceiveBuffer.ToArray(), bufferOffset, WsPayloadSize);
                        }
                        else if ((opcode & WS_PONG) == WS_PONG)
                        {
                            // Call the WebSocket pong handler
                            _wsHandler.OnWsPong(WsReceiveBuffer.ToArray(), bufferOffset, WsPayloadSize);
                        }
                        else if ((opcode & WS_CLOSE) == WS_CLOSE)
                        {
                            // Call the WebSocket close handler
                            _wsHandler.OnWsClose(WsReceiveBuffer.ToArray(), bufferOffset, WsPayloadSize);
                        }
                        else if (((opcode & WS_TEXT) == WS_TEXT) || ((opcode & WS_BINARY) == WS_BINARY))
                        {
                            // Call the WebSocket received handler
                            _wsHandler.OnWsReceived(WsReceiveBuffer.ToArray(), bufferOffset, WsPayloadSize);
                        }
                    }
                }
            }
        }