Example #1
0
        /// <summary>
        /// Clear WebSocket send/receive buffers
        /// </summary>
        public void ClearWsBuffers()
        {
            lock (WsReceiveLock)
            {
                WsFrameReceived = false;
                WsFinalReceived = false;
                WsHeaderSize    = 0;
                WsPayloadSize   = 0;
                WsReceiveFrameBuffer.Clear();
                WsReceiveFinalBuffer.Clear();
                Array.Clear(WsReceiveMask, 0, WsReceiveMask.Length);
            }

            lock (WsSendLock)
            {
                WsSendBuffer.Clear();
                Array.Clear(WsSendMask, 0, WsSendMask.Length);
            }
        }
Example #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, 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;
                            }
                            }
                        }
                    }
                }
            }
        }