Пример #1
0
        static ArrayBuffer CopyMessageToBuffer(BufferPool bufferPool, bool expectMask, byte[] buffer, int msgOffset, int payloadLength)
        {
            ArrayBuffer arrayBuffer = bufferPool.Take(payloadLength);

            if (expectMask)
            {
                int maskOffset = msgOffset - Constants.MaskSize;
                // write the result of toggle directly into arrayBuffer to avoid 2nd copy call
                MessageProcessor.ToggleMask(buffer, msgOffset, arrayBuffer, payloadLength, buffer, maskOffset);
            }
            else
            {
                arrayBuffer.CopyFrom(buffer, msgOffset, payloadLength);
            }

            return(arrayBuffer);
        }
Пример #2
0
        static void HandleCloseMessage(Config config, byte[] buffer, int msgOffset, int payloadLength)
        {
            (Connection conn, int _, bool expectMask, ConcurrentQueue <Message> _, BufferPool _) = config;

            if (expectMask)
            {
                int maskOffset = msgOffset - Constants.MaskSize;
                MessageProcessor.ToggleMask(buffer, msgOffset, payloadLength, buffer, maskOffset);
            }

            // dump after mask off
            Log.DumpBuffer($"Message", buffer, msgOffset, payloadLength);

            Log.Info($"Close: {GetCloseCode(buffer, msgOffset)} message:{GetCloseMessage(buffer, msgOffset, payloadLength)}");

            conn.Dispose();
        }
Пример #3
0
        static void ReadOneMessage(Config config, byte[] buffer)
        {
            (Connection conn, int maxMessageSize, bool expectMask, ConcurrentQueue <Message> queue, BufferPool bufferPool) = config;
            Stream stream = conn.stream;

            int offset = 0;

            // read 2
            offset = ReadHelper.Read(stream, buffer, offset, Constants.HeaderMinSize);
            // log after first blocking call
            Log.Verbose($"Message From {conn}");

            if (MessageProcessor.NeedToReadShortLength(buffer))
            {
                offset = ReadHelper.Read(stream, buffer, offset, Constants.ShortLength);
            }


            MessageProcessor.ValidateHeader(buffer, maxMessageSize, expectMask);

            if (expectMask)
            {
                offset = ReadHelper.Read(stream, buffer, offset, Constants.MaskSize);
            }

            int opcode        = MessageProcessor.GetOpcode(buffer);
            int payloadLength = MessageProcessor.GetPayloadLength(buffer);

            Log.Verbose($"Header ln:{payloadLength} op:{opcode} mask:{expectMask}");
            Log.DumpBuffer($"Raw Header", buffer, 0, offset);

            int msgOffset = offset;

            offset = ReadHelper.Read(stream, buffer, offset, payloadLength);

            switch (opcode)
            {
            case 2:
                HandleArrayMessage(config, buffer, msgOffset, payloadLength);
                break;

            case 8:
                HandleCloseMessage(config, buffer, msgOffset, payloadLength);
                break;
            }
        }
Пример #4
0
        static void HandleArrayMessage(Config config, byte[] buffer, int msgOffset, int payloadLength)
        {
            (Connection conn, int _, bool expectMask, ConcurrentQueue <Message> queue, BufferPool bufferPool) = config;

            ArrayBuffer arrayBuffer = bufferPool.Take(payloadLength);

            if (expectMask)
            {
                int maskOffset = msgOffset - Constants.MaskSize;
                // write the result of toggle directly into arrayBuffer to avoid 2nd copy call
                MessageProcessor.ToggleMask(buffer, msgOffset, arrayBuffer, payloadLength, buffer, maskOffset);
            }
            else
            {
                arrayBuffer.CopyFrom(buffer, msgOffset, payloadLength);
            }

            // dump after mask off
            Log.DumpBuffer($"Message", arrayBuffer);

            queue.Enqueue(new Message(conn.connId, arrayBuffer));
        }
Пример #5
0
        static Header ReadHeader(Config config, byte[] buffer, bool opCodeContinuation = false)
        {
            (Connection conn, int maxMessageSize, bool expectMask, ConcurrentQueue <Message> queue, BufferPool bufferPool) = config;
            Stream stream = conn.stream;
            Header header = new Header();

            // read 2
            header.offset = ReadHelper.Read(stream, buffer, header.offset, Constants.HeaderMinSize);
            // log after first blocking call
            Log.Verbose($"Message From {conn}");

            if (MessageProcessor.NeedToReadShortLength(buffer))
            {
                header.offset = ReadHelper.Read(stream, buffer, header.offset, Constants.ShortLength);
            }
            if (MessageProcessor.NeedToReadLongLength(buffer))
            {
                header.offset = ReadHelper.Read(stream, buffer, header.offset, Constants.LongLength);
            }

            Log.DumpBuffer($"Raw Header", buffer, 0, header.offset);

            MessageProcessor.ValidateHeader(buffer, maxMessageSize, expectMask, opCodeContinuation);

            if (expectMask)
            {
                header.offset = ReadHelper.Read(stream, buffer, header.offset, Constants.MaskSize);
            }

            header.opcode        = MessageProcessor.GetOpcode(buffer);
            header.payloadLength = MessageProcessor.GetPayloadLength(buffer);
            header.finished      = MessageProcessor.Finished(buffer);

            Log.Verbose($"Header ln:{header.payloadLength} op:{header.opcode} mask:{expectMask}");

            return(header);
        }
Пример #6
0
        /// <returns>new offset in buffer</returns>
        static int SendMessage(byte[] buffer, int startOffset, ArrayBuffer msg, bool setMask, MaskHelper maskHelper)
        {
            int msgLength = msg.count;
            int offset    = WriteHeader(buffer, startOffset, msgLength, setMask);

            if (setMask)
            {
                offset = maskHelper.WriteMask(buffer, offset);
            }

            msg.CopyTo(buffer, offset);
            offset += msgLength;

            // dump before mask on
            Log.DumpBuffer("Send", buffer, startOffset, offset);

            if (setMask)
            {
                int messageOffset = offset - msgLength;
                MessageProcessor.ToggleMask(buffer, messageOffset, msgLength, buffer, messageOffset - Constants.MaskSize);
            }

            return(offset);
        }
Пример #7
0
        static void SendMessage(Stream stream, byte[] buffer, ArrayBuffer msg, bool setMask, MaskHelper maskHelper)
        {
            int msgLength  = msg.count;
            int sendLength = WriteHeader(buffer, msgLength, setMask);

            if (setMask)
            {
                sendLength = maskHelper.WriteMask(buffer, sendLength);
            }

            msg.CopyTo(buffer, sendLength);
            sendLength += msgLength;

            // dump before mask on
            Log.DumpBuffer("Send", buffer, 0, sendLength);

            if (setMask)
            {
                int messageOffset = sendLength - msgLength;
                MessageProcessor.ToggleMask(buffer, messageOffset, msgLength, buffer, messageOffset - Constants.MaskSize);
            }

            stream.Write(buffer, 0, sendLength);
        }
Пример #8
0
        static void ReadOneMessage(Config config, byte[] buffer)
        {
            (Connection conn, int maxMessageSize, bool expectMask, ConcurrentQueue <Message> queue, BufferPool bufferPool) = config;
            Stream stream = conn.stream;

            Header header = ReadHeader(config, buffer);

            int msgOffset = header.offset;

            header.offset = ReadHelper.Read(stream, buffer, header.offset, header.payloadLength);

            if (header.finished)
            {
                switch (header.opcode)
                {
                case 2:
                    HandleArrayMessage(config, buffer, msgOffset, header.payloadLength);
                    break;

                case 8:
                    HandleCloseMessage(config, buffer, msgOffset, header.payloadLength);
                    break;
                }
            }
            else
            {
                // todo cache this to avoid allocations
                Queue <ArrayBuffer> fragments = new Queue <ArrayBuffer>();
                fragments.Enqueue(CopyMessageToBuffer(bufferPool, expectMask, buffer, msgOffset, header.payloadLength));
                int totalSize = header.payloadLength;

                while (!header.finished)
                {
                    header = ReadHeader(config, buffer, opCodeContinuation: true);

                    msgOffset     = header.offset;
                    header.offset = ReadHelper.Read(stream, buffer, header.offset, header.payloadLength);
                    fragments.Enqueue(CopyMessageToBuffer(bufferPool, expectMask, buffer, msgOffset, header.payloadLength));

                    totalSize += header.payloadLength;
                    MessageProcessor.ThrowIfMsgLengthTooLong(totalSize, maxMessageSize);
                }


                ArrayBuffer msg = bufferPool.Take(totalSize);
                msg.count = 0;
                while (fragments.Count > 0)
                {
                    ArrayBuffer part = fragments.Dequeue();

                    part.CopyTo(msg.array, msg.count);
                    msg.count += part.count;

                    part.Release();
                }

                // dump after mask off
                Log.DumpBuffer($"Message", msg);

                queue.Enqueue(new Message(conn.connId, msg));
            }
        }