Beispiel #1
0
        public WSHandler(WSConnection connection, IWSConnectionParameters options)
        {
            if (connection == null)
            {
                throw new ArgumentNullException(nameof(connection), $"{nameof(connection)} is null.");
            }

            if (options == null)
            {
                throw new ArgumentNullException(nameof(options), $"{nameof(options)} is null.");
            }


            var buffers = connection.Buffers;

            if (buffers.IsIncomplete)
            {
                throw new NotSupportedException($"{nameof(WSConnection.Buffers)} is incomplete");
            }

            Connection     = connection;
            ReadOperations = new WSOperations(buffers, options);
            SendOperations = new WSOperations(buffers, options);

            Stopwatch = new Stopwatch();

            Heartbeat  = options.Heartbeat;
            ByteBuffer = buffers.ByteBuffer;
            CharBuffer = buffers.CharBuffer;
        }
Beispiel #2
0
        public async Task HeartbeatAsync(CancellationToken cancellationToken = default)
        {
            if (Heartbeat < TimeSpan.FromMilliseconds(1))
            {
                return;
            }

            if (Stopwatch.IsRunning)
            {
                return;
            }

            Stopwatch.Restart();

            var task      = HeartbeatTaskCompletionSource.Task;
            var random    = new Random();
            var pulser    = default(Task <bool>);
            var readFrame = default(WSFrame);

            using (var sendFragment = ByteBuffer.GetFragment(200)) {
                var sendSegment = sendFragment.GetSegment();

                while (cancellationToken.IsCancellationRequested == false)
                {
                    var delay = Heartbeat - Stopwatch.Elapsed;
                    if (delay.Ticks > 0)
                    {
                        var result = await Task.WhenAny(task, Task.Delay(delay));

                        if (result == task)
                        {
                            break;
                        }
                    }
                    else
                    {
                        using (await WaitForSendLock(cancellationToken)) {
                            WSOperations.Scramble(sendSegment);

                            pulser = Task.Run(delegate {
                                return(Pulser.Wait(out readFrame, 3000));
                            });

                            await SendOperations.SendFrame(new WSFrame {
                                Fragment = sendFragment,
                                Code     = WSConsts.CodePing,
                                Last     = true,
                            }, cancellationToken);
                        }

                        if (await pulser)
                        {
                            using (var readFragment = readFrame.Fragment) {
                                var readSegment = readFragment.GetSegment();

                                if (readFrame.Code == WSConsts.CodePong && readFrame.Last && readSegment.SequenceEqual(sendSegment))
                                {
                                    continue;
                                }
                                else
                                {
                                    throw new NotSupportedException("Pong is incorrect");
                                }
                            }
                        }

                        throw new NotSupportedException("Pong is incorrect");
                    }
                }

                Stopwatch.Reset();
            }
        }