unsafe void IMessageWriter.Write(ref WritableBuffer buffer)
        {
            int expected = GetTotalBytes();

            if (expected == 0)
            {
                return;
            }


            var   memory = buffer.Memory;
            byte *dest   = (byte *)memory.BufferPtr;
            int   actual;

            fixed(char *chars = value)
            {
#if ENCODING_POINTER_API
                var enc = Interlocked.Exchange(ref sharedEncoder, null);
                if (enc == null)
                {
                    enc = encoding.GetEncoder();              // need a new one
                }
                actual = enc.GetBytes(chars + offset, count, dest, expected, true);
                Interlocked.CompareExchange(ref sharedEncoder, enc, null); // make the encoder available  for re-use
#else
                actual = encoding.GetBytes(chars + offset, count, dest, expected);
#endif
            }

            if (actual != expected)
            {
                throw new InvalidOperationException($"Unexpected length in {nameof(StringMessageWriter)}.{nameof(IMessageWriter.Write)}");
            }
            buffer.CommitBytes(actual);
        }
        public static unsafe void WriteUtf8String(ref WritableBuffer buffer, string value)
        {
            fixed(char *s = value)
            {
                var byteCount = Utf8Encoding.GetByteCount(value);

                buffer.Ensure(byteCount);
                int written = Utf8Encoding.GetBytes(s, value.Length, (byte *)buffer.Memory.BufferPtr, byteCount);

                buffer.CommitBytes(written);
            }
        }
        public static unsafe void WriteAsciiString(ref WritableBuffer buffer, string value)
        {
            // One byte per char
            buffer.Ensure(value.Length);

            fixed(char *s = value)
            {
                int written = ASCIIEncoding.GetBytes(s, value.Length, (byte *)buffer.Memory.BufferPtr, value.Length);

                buffer.CommitBytes(written);
            }
        }
Example #4
0
        private void OnRead(UvStreamHandle handle, int status)
        {
            if (status == 0)
            {
                // A zero status does not indicate an error or connection end. It indicates
                // there is no data to be read right now.
                // See the note at http://docs.libuv.org/en/v1.x/stream.html#c.uv_read_cb.
                // We need to clean up whatever was allocated by OnAlloc.
                _inputBuffer.FlushAsync();
                return;
            }

            var normalRead = status > 0;
            var normalDone = status == EOF;
            var errorDone  = !(normalDone || normalRead);
            var readCount  = normalRead ? status : 0;

            if (!normalRead)
            {
                handle.ReadStop();
            }

            _inputBuffer.CommitBytes(readCount);

            IOException error = null;

            if (errorDone)
            {
                Exception uvError;
                handle.Libuv.Check(status, out uvError);
                error = new IOException(uvError.Message, uvError);

                _input.CompleteWriting(error);
            }
            else if (readCount == 0 || _input.ReaderCompleted.IsCompleted)
            {
                _input.CompleteWriting();
            }
            else
            {
                var task = _inputBuffer.FlushAsync();

                if (!task.IsCompleted)
                {
                    // If there's back pressure
                    handle.ReadStop();

                    // Resume reading when task continues
                    task.ContinueWith((t, state) => ((UvTcpConnection)state).StartReading(), this);
                }
            }
        }
Example #5
0
        private void OnRead(UvStreamHandle handle, int status)
        {
            if (status == 0)
            {
                // A zero status does not indicate an error or connection end. It indicates
                // there is no data to be read right now.
                // See the note at http://docs.libuv.org/en/v1.x/stream.html#c.uv_read_cb.
                // We need to clean up whatever was allocated by OnAlloc.
                return;
            }

            var normalRead = status > 0;
            var normalDone = status == EOF;
            var errorDone  = !(normalDone || normalRead);
            var readCount  = normalRead ? status : 0;

            if (!normalRead)
            {
                handle.ReadStop();
            }

            _inputBuffer.CommitBytes(readCount);

            IOException error = null;

            if (errorDone)
            {
                Exception uvError;
                handle.Libuv.Check(status, out uvError);
                error = new IOException(uvError.Message, uvError);

                _input.CompleteWriting(error);
            }
            else if (readCount == 0)
            {
                _input.CompleteWriting();
            }
            else
            {
                var task = _input.WriteAsync(_inputBuffer);

                if (task.IsFaulted)
                {
                    // TODO: Stop producing forever
                }
                else if (!task.IsCompleted)
                {
                    // TODO: Pause reading until the task completes
                }
            }
        }
Example #6
0
        public void ReceiveBeginComplete(uint bytesTransferred)
        {
            if (bytesTransferred == 0 || _input.ReaderCompleted.IsCompleted)
            {
                _input.CompleteWriting();
            }
            else
            {
                _buffer.CommitBytes((int)bytesTransferred);
                _buffer.Commit();

                ProcessReceives();
            }
        }
        internal static unsafe void WriteFrameHeader(ref WritableBuffer output, WebSocketsFrame.FrameFlags flags, WebSocketsFrame.OpCodes opCode, int payloadLength, int mask)
        {
            byte *buffer = (byte *)output.Memory.BufferPtr;

            int bytesWritten;

            *buffer++ = (byte)(((int)flags & 240) | ((int)opCode & 15));
            if (payloadLength > ushort.MaxValue)
            { // write as a 64-bit length
                *buffer++ = (byte)((mask != 0 ? 128 : 0) | 127);
                *buffer++ = 0;
                *buffer++ = 0;
                *buffer++ = 0;
                *buffer++ = 0;
                *buffer++ = (byte)(payloadLength >> 24);
                *buffer++ = (byte)(payloadLength >> 16);
                *buffer++ = (byte)(payloadLength >> 8);
                *buffer++ = (byte)(payloadLength);
                bytesWritten = 10;
            }
            else if (payloadLength > 125)
            { // write as a 16-bit length
                *buffer++ = (byte)((mask != 0 ? 128 : 0) | 126);
                *buffer++ = (byte)(payloadLength >> 8);
                *buffer++ = (byte)(payloadLength);
                bytesWritten = 4;
            }
            else
            { // write in the header
                *buffer++ = (byte)((mask != 0 ? 128 : 0) | payloadLength);
                bytesWritten = 2;
            }
            if (mask != 0)
            {
                *buffer++ = (byte)(mask >> 24);
                *buffer++ = (byte)(mask >> 16);
                *buffer++ = (byte)(mask >> 8);
                *buffer++ = (byte)(mask);
                bytesWritten += 4;
            }
            output.CommitBytes(bytesWritten);
        }
Example #8
0
        public void Complete(int status, long requestCorrelation, uint bytesTransferred)
        {
            // Receives
            if (requestCorrelation >= 0)
            {
                if (bytesTransferred == 0 || _input.ReaderCompleted.IsCompleted)
                {
                    _input.CompleteWriting();
                }
                else
                {
                    _buffer.CommitBytes((int)bytesTransferred);
                    _buffer.FlushAsync();

                    ProcessReceives();
                }
            }
            else
            {
                SendCompleting(requestCorrelation);
            }
        }
Example #9
0
        public void Complete(int status, long requestCorrelation, uint bytesTransferred)
        {
            // Receives
            if (requestCorrelation >= 0)
            {
                if (bytesTransferred > 0)
                {
                    _buffer.CommitBytes((int)bytesTransferred);
                    _input.WriteAsync(_buffer);

                    ProcessReceives();
                }
                else
                {
                    _input.CompleteWriting();
                }
            }
            else
            {
                SendCompleting(requestCorrelation);
            }
        }
 public void CommitBytes(int bytes)
 {
     _writableBuffer.CommitBytes(bytes);
 }
Example #11
0
        public static unsafe void WriteUInt64(ref WritableBuffer buffer, ulong value)
        {
            // optimized versions for 0-1000
            int   len;
            byte *addr;

            if (value < 10)
            {
                buffer.Ensure(len = 1);
                addr = (byte *)buffer.Memory.UnsafePointer;
                *addr = (byte)('0' + value);
            }
            else if (value < 100)
            {
                buffer.Ensure(len = 2);
                addr = (byte *)buffer.Memory.UnsafePointer;
                *addr++ = (byte)('0' + value / 10);
                *addr   = (byte)('0' + value % 10);
            }
            else if (value < 1000)
            {
                buffer.Ensure(len = 3);
                addr    = (byte *)buffer.Memory.UnsafePointer;
                addr[2] = (byte)('0' + value % 10);
                value  /= 10;
                *addr++ = (byte)('0' + value / 10);
                *addr   = (byte)('0' + value % 10);
            }
            else
            {
                // more generic version for all other numbers; first find the number of digits;
                // lost of ways to do this, but: http://stackoverflow.com/a/6655759/23354
                ulong remaining = value;
                len = 1;
                if (remaining >= 10000000000000000)
                {
                    remaining /= 10000000000000000; len += 16;
                }
                if (remaining >= 100000000)
                {
                    remaining /= 100000000; len += 8;
                }
                if (remaining >= 10000)
                {
                    remaining /= 10000; len += 4;
                }
                if (remaining >= 100)
                {
                    remaining /= 100; len += 2;
                }
                if (remaining >= 10)
                {
                    remaining /= 10; len += 1;
                }
                buffer.Ensure(len);

                // now we'll walk *backwards* from the last character, adding the digit each time
                // and dividing by 10
                addr = (byte *)buffer.Memory.UnsafePointer + len;
                do
                {
                    *--addr = (byte)('0' + value % 10);
                    value  /= 10;
                } while (value != 0);
            }
            buffer.CommitBytes(len);
        }