Ejemplo n.º 1
0
        private Task OnConectionFrameReceivedImplAsync(WebSocketsFrame.OpCodes opCode, ref Message message)
        {
            WebSocketServer.WriteStatus(connectionType, $"Processing {opCode}, {message.GetPayloadLength()} bytes...");
            switch (opCode)
            {
            case WebSocketsFrame.OpCodes.Binary:
                return(OnBinaryAsync(ref message));

            case WebSocketsFrame.OpCodes.Text:
                return(OnTextAsync(ref message));

            case WebSocketsFrame.OpCodes.Close:
                connection.Input.Complete();
                // respond to a close in-kind (2-handed close)
                try { Closed?.Invoke(); } catch { }

                if (connection.Output.Writing.IsCompleted)
                {
                    return(TaskResult.True);                                           // already closed
                }
                return(SendAsync(WebSocketsFrame.OpCodes.Close, ref message));

            case WebSocketsFrame.OpCodes.Ping:
                // by default, respond to a ping with a matching pong
                return(SendAsync(WebSocketsFrame.OpCodes.Pong, ref message));    // right back at you

            case WebSocketsFrame.OpCodes.Pong:
                return(TaskResult.True);

            default:
                return(TaskResult.True);
            }
        }
Ejemplo n.º 2
0
        private async Task SendAsyncImpl <T>(WebSocketsFrame.OpCodes opCode, T message) where T : struct, IMessageWriter
        {
            //TODO: come up with a better way of getting ordered access to the socket
            var  writeLock = GetWriteSemaphore();
            bool haveLock  = writeLock.Wait(0);

            if (!haveLock)
            {   // try to acquire asynchronously instead, then
                await writeLock.WaitAsync();
            }
            try
            {
                WebSocketServer.WriteStatus($"Writing {opCode} message...");
                await WebSocketProtocol.WriteAsync(this, opCode, ref message);

                if (opCode == WebSocketsFrame.OpCodes.Close)
                {
                    Close();
                }
            }
            finally
            {
                writeLock.Release();
            }
        }
Ejemplo n.º 3
0
        internal static Task WriteAsync <T>(WebSocketConnection connection,
                                            WebSocketsFrame.OpCodes opCode,
                                            WebSocketsFrame.FrameFlags flags, ref T message)
            where T : struct, IMessageWriter
        {
            int payloadLength = message.GetPayloadLength();
            var buffer        = connection.Connection.Output.Alloc(MaxHeaderLength + payloadLength);
            int mask          = connection.ConnectionType == ConnectionType.Client ? CreateMask() : 0;

            WriteFrameHeader(ref buffer, WebSocketsFrame.FrameFlags.IsFinal, opCode, payloadLength, mask);
            if (payloadLength != 0)
            {
                if (mask == 0)
                {
                    message.WritePayload(buffer);
                }
                else
                {
                    var payloadStart = buffer.AsReadableBuffer().End;
                    message.WritePayload(buffer);
                    var payload = buffer.AsReadableBuffer().Slice(payloadStart); // note that this is a different AsReadableBuffer; call twice is good
                    WebSocketsFrame.ApplyMask(ref payload, mask);
                }
            }
            return(buffer.FlushAsync().AsTask());
        }
Ejemplo n.º 4
0
        private async Task SendAsyncImpl <T>(WebSocketsFrame.OpCodes opCode, T message, WebSocketsFrame.FrameFlags flags) where T : struct, IMessageWriter
        {
            //TODO: come up with a better way of getting ordered access to the socket
            var  writeLock = GetWriteSemaphore();
            bool haveLock  = writeLock.Wait(0);

            if (!haveLock)
            {   // try to acquire asynchronously instead, then
                await writeLock.WaitAsync();
            }
            try
            {
                WebSocketServer.WriteStatus(ConnectionType, $"Writing {opCode} message ({message.GetPayloadLength()} bytes)...");
                await WebSocketProtocol.WriteAsync(this, opCode, flags, ref message);

                if (opCode == WebSocketsFrame.OpCodes.Close)
                {
                    connection.Output.Complete();
                }
            }
            finally
            {
                writeLock.Release();
            }
        }
Ejemplo n.º 5
0
 internal Task SendAsync(WebSocketsFrame.OpCodes opCode, ref Message message, WebSocketsFrame.FrameFlags flags = WebSocketsFrame.FrameFlags.IsFinal)
 {
     if (connection.Output.Writing.IsCompleted)
     {
         throw new InvalidOperationException("Connection has been closed");
     }
     return(SendAsyncImpl(opCode, message, flags));
 }
Ejemplo n.º 6
0
        private Task OnServerFrameReceivedImplAsync(WebSocketsFrame.OpCodes opCode, ref Message message, WebSocketServer server)
        {
            switch (opCode)
            {
            case WebSocketsFrame.OpCodes.Binary:
                return(server.OnBinaryAsync(this, ref message));

            case WebSocketsFrame.OpCodes.Text:
                return(server.OnTextAsync(this, ref message));
            }
            return(TaskResult.True);
        }
        internal static Task WriteAsync <T>(WebSocketConnection connection, WebSocketsFrame.OpCodes opCode, ref T message)
            where T : struct, IMessageWriter
        {
            int payloadLength = message.GetTotalBytes();
            var buffer        = connection.Connection.Output.Alloc(MaxHeaderLength + payloadLength);

            WriteFrameHeader(ref buffer, WebSocketsFrame.FrameFlags.IsFinal, opCode, payloadLength, 0);
            if (payloadLength != 0)
            {
                message.Write(ref buffer);
            }
            return(buffer.FlushAsync());
        }
Ejemplo n.º 8
0
        internal WebSocketsFrame.OpCodes GetEffectiveOpCode(ref WebSocketsFrame frame)
        {
            if (frame.IsControlFrame)
            {
                // doesn't change state
                return(frame.OpCode);
            }

            var frameOpCode = frame.OpCode;

            // re-use the previous opcode if we are a continuation
            var result = frameOpCode == WebSocketsFrame.OpCodes.Continuation ? lastOpCode : frameOpCode;

            // if final, clear the opcode; otherwise: use what we thought of
            lastOpCode = frame.IsFinal ? WebSocketsFrame.OpCodes.Continuation : result;
            return(result);
        }
        private async Task <int> BroadcastAsync <T>(WebSocketsFrame.OpCodes opCode, T message, Func <WebSocketConnection, bool> predicate) where T : struct, IMessageWriter
        {
            int count = 0;

            foreach (var pair in connections)
            {
                var conn = pair.Key;
                if (!conn.IsClosed && (predicate == null || predicate(conn)))
                {
                    try
                    {
                        await conn.SendAsync <T>(opCode, ref message);

                        count++;
                    }
                    catch { } // not really all that bothered - they just won't get counted
                }
            }
            return(count);
        }
Ejemplo n.º 10
0
        private Task OnFrameReceivedImplAsync(WebSocketConnection connection, WebSocketsFrame.OpCodes opCode, ref Message message)
        {
            switch (opCode)
            {
            case WebSocketsFrame.OpCodes.Binary:
                return(OnBinaryAsync(connection, ref message));

            case WebSocketsFrame.OpCodes.Text:
                return(OnTextAsync(connection, ref message));

            case WebSocketsFrame.OpCodes.Close:
                return(OnCloseAsync(connection, ref message));

            case WebSocketsFrame.OpCodes.Ping:
                return(OnPingAsync(connection, ref message));

            case WebSocketsFrame.OpCodes.Pong:
                return(OnPongAsync(connection, ref message));

            default:
                return(TaskResult.True);
            }
        }
Ejemplo n.º 11
0
 internal Task SendAsync <T>(WebSocketsFrame.OpCodes opCode, ref T message, WebSocketsFrame.FrameFlags flags = WebSocketsFrame.FrameFlags.IsFinal) where T : struct, IMessageWriter
 {
     return(SendAsyncImpl(opCode, message, flags));
 }
Ejemplo n.º 12
0
 internal Task SendAsync <T>(WebSocketsFrame.OpCodes opCode, ref T message) where T : struct, IMessageWriter
 {
     CheckCanSend();
     return(SendAsyncImpl(opCode, message));
 }
Ejemplo n.º 13
0
        private void Process(NetContext context, Connection connection, Stream stream, WebSocketsFrame.OpCodes opCode)
        {
            using (stream)
            {
                switch (opCode)
                {
                case WebSocketsFrame.OpCodes.Text:
                    string s;
                    if (stream == null || stream.Length == 0)
                    {
                        s = "";
                    }
                    else
                    {
                        stream.Position = 0;
                        using (var reader = new StreamReader(stream, Encoding.UTF8))
                        {
                            s = reader.ReadToEnd();
                        }
                    }
                    context.Handler.OnReceived(connection, s);
                    break;

                case WebSocketsFrame.OpCodes.Binary:
                    byte[] blob;
                    int    len;
                    if (stream == null || (len = ((int)stream.Length - (int)stream.Position)) == 0)
                    {
                        blob = new byte[0];
                    }
                    else
                    {
                        blob = new byte[len];
                        byte[] buffer = null;
                        try
                        {
                            buffer = context.GetBuffer();
                            int offset = 0, read;
                            stream.Position = 0;
                            while ((read = stream.Read(buffer, offset, Math.Min(len, buffer.Length))) > 0)
                            {
                                offset += read;
                                len    -= read;
                            }
                            if (len != 0)
                            {
                                throw new EndOfStreamException();
                            }
                        } finally
                        {
                            context.Recycle(buffer);
                        }
                    }
                    context.Handler.OnReceived(connection, blob);
                    break;

                default:
                    throw new InvalidOperationException();
                }
            }
        }
Ejemplo n.º 14
0
        internal static void WriteFrameHeader(ref WritableBuffer output, WebSocketsFrame.FrameFlags flags, WebSocketsFrame.OpCodes opCode, int payloadLength, int mask)
        {
            output.Ensure(MaxHeaderLength);

            int index = 0;
            var span  = output.Buffer.Span;

            span[index++] = (byte)(((int)flags & 240) | ((int)opCode & 15));
            if (payloadLength > ushort.MaxValue)
            { // write as a 64-bit length
                span[index++] = (byte)((mask != 0 ? 128 : 0) | 127);
                span.Slice(index).Write((uint)0);
                span.Slice(index + 4).Write(ToNetworkByteOrder((uint)payloadLength));
                index += 8;
            }
            else if (payloadLength > 125)
            { // write as a 16-bit length
                span[index++] = (byte)((mask != 0 ? 128 : 0) | 126);
                span.Slice(index).Write(ToNetworkByteOrder((ushort)payloadLength));
                index += 2;
            }
            else
            { // write in the header
                span[index++] = (byte)((mask != 0 ? 128 : 0) | payloadLength);
            }
            if (mask != 0)
            {
                span.Slice(index).Write(mask);
                index += 4;
            }
            output.Advance(index);
        }
Ejemplo n.º 15
0
 internal Task SendAsync(WebSocketsFrame.OpCodes opCode, ref Message message)
 {
     CheckCanSend();
     return(SendAsyncImpl(opCode, message));
 }
        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);
        }
Ejemplo n.º 17
0
 private async Task OnServerAndConnectionFrameReceivedImplAsync(WebSocketsFrame.OpCodes opCode, Message message, WebSocketServer server)
 {
     await OnConectionFrameReceivedImplAsync(opCode, ref message);
     await OnServerFrameReceivedImplAsync(opCode, ref message, server);
 }