public override bool Process(WebSocketPackage package, ref SequenceReader <byte> reader, out IPackagePartReader <WebSocketPackage> nextPartReader, out bool needMoreData)
        {
            nextPartReader = null;

            long required = package.PayloadLength;

            if (reader.Remaining < required)
            {
                needMoreData = true;
                return(false);
            }

            needMoreData = false;

            var seq = reader.Sequence.Slice(reader.Consumed, required);

            if (package.HasMask)
            {
                DecodeMask(ref seq, package.MaskKey);
            }

            try
            {
                if (package.Data.Length == 0)
                {
                    package.Data = seq;
                }
                else
                {
                    var currentData = package.Data;
                    package.Data = ConcactSequence(ref currentData, ref seq);
                }

                if (package.FIN)
                {
                    if (package.OpCode == OpCode.Text)
                    {
                        package.Message = package.Data.GetString(Encoding.UTF8);
                        package.Data    = default;
                    }
                    else
                    {
                        var data = package.Data;
                        package.Data = CopySequence(ref data);
                    }

                    return(true);
                }
                else
                {
                    // start to process next fragment
                    nextPartReader = FixPartReader;
                    return(false);
                }
            }
            finally
            {
                reader.Advance(required);
            }
        }
Exemple #2
0
        internal async ValueTask OnPingReceived(WebSocketPackage ping)
        {
            ping.OpCode = OpCode.Pong;
            await WebSocket.SendAsync(ping);

            LastPingReceived = DateTimeOffset.Now;
        }
Exemple #3
0
        public override bool Process(WebSocketPackage package, object filterContext, ref SequenceReader <byte> reader, out IPackagePartReader <WebSocketPackage> nextPartReader, out bool needMoreData)
        {
            int required = 4;

            if (reader.Remaining < required)
            {
                nextPartReader = null;
                needMoreData   = true;
                return(false);
            }

            needMoreData = false;

            package.MaskKey = reader.Sequence.Slice(reader.Consumed, 4).ToArray();
            reader.Advance(4);

            if (TryInitIfEmptyMessage(package))
            {
                nextPartReader = null;
                return(true);
            }

            nextPartReader = PayloadDataReader;
            return(false);
        }
Exemple #4
0
        private async Task ProcessRemoved(WebSocketPackage webSocketPackage)
        {
            var file = await FileRepository.FindAsync(AccountObject.Token, webSocketPackage.UploadId);

            if (file == null)
            {
                return;
            }

            //detect moved files
            var created = await FileRepository.FindAsync(x =>
                                                         x.Size == file.Size &&
                                                         x.Status == FileStatus.RemotelyCreated &&
                                                         x.Name == file.Name &&
                                                         x.Crc32 == file.Crc32 &&
                                                         x.UploadId != file.UploadId);

            if (created != null)
            {
                created.Status  = FileStatus.RemotelyMovedTo;
                created.MovedId = file.Id;
                file.Status     = FileStatus.RemotelyMovedFrom;
                file.MovedId    = file.Id;
                return;
            }

            file.Status = file.Status == FileStatus.Synchronized
                ? FileStatus.RemotelyDeleted
                : FileStatus.Conflict;
        }
Exemple #5
0
        private async Task Process(WebSocketPackage webSocketPackage)
        {
            switch (webSocketPackage.ActionId)
            {
            case WebSocketAction.ObjectHistoryRenameFolder:
            case WebSocketAction.ObjectHistoryRenameUpload:
                await ProcessMoved(webSocketPackage);

                break;

            case WebSocketAction.ObjectHistoryDeleteFolder:
            case WebSocketAction.ObjectHistoryDeleteUpload:
                await ProcessRemoved(webSocketPackage);

                break;

            case WebSocketAction.ObjectHistoryCreateFolder:
            case WebSocketAction.ObjectHistoryCreateUpload:
                await ProcessCreated(webSocketPackage);

                break;

            case WebSocketAction.ObjectHistoryCopyFolder:
                await ProcessCopy(webSocketPackage);

                break;
            }

            Packages.Remove(webSocketPackage);
        }
Exemple #6
0
 private async Task ProcessCopy(WebSocketPackage webSocketPackage)
 {
     //TODO: currently there is no way to guess which folder was copied, all we can do is scan this folder and download
     //TODO: it is EXTREMELY unefficient, web api SHOULD be improved
     var command = new RemoteFileScanObjectCommand(FileRepository, Connection, AccountObject, webSocketPackage);
     await command.Execute(_cancellationToken);
 }
Exemple #7
0
        public ValueTask HandleIncoming(WebSocketSession session, WebSocketPackage pkg)
        {
            var msg = _messageFactory.Parse(pkg.Message);

            if (msg == null)
            {
                return(new ValueTask());
            }

            if (msg is IPingMessage)
            {
                return(session.SendAsync("{\"type\": \"pong\"}"));
            }

            if (msg is IStateChangeMessage stateChange)
            {
                return(_stateManager.ChangeState(stateChange.NewState));
            }
            else if (msg is IBlinkSpeedMessage speedChange)
            {
                _fp.BlinkPeriodMs = speedChange.Speed > 0
                    ? speedChange.Speed
                    : 500;

                return(new ValueTask());
            }

            return(_stateManager.State.HandleIncoming(msg));
        }
Exemple #8
0
        private void EncodeTextMessage(WebSocketPackage package)
        {
            var encoder = _encoding.GetEncoder();
            var text    = package.Message.AsSpan();

            var completed = false;

            var outputStream = new WritableSequenceStream();

            using (var stream = new DeflateStream(outputStream, CompressionMode.Compress))
            {
                while (!completed)
                {
                    var         buffer = _arrayPool.Rent(_deflateBufferSize);
                    Span <byte> span   = buffer;

                    encoder.Convert(text, span, false, out int charsUsed, out int bytesUsed, out completed);

                    if (charsUsed > 0)
                    {
                        text = text.Slice(charsUsed);
                    }

                    stream.Write(buffer, 0, bytesUsed);
                }

                stream.Flush();
            }

            package.Data = outputStream.GetUnderlyingSequence();
        }
Exemple #9
0
        private async Task ProcessMoved(WebSocketPackage webSocketPackage)
        {
            var file = await FileRepository.FindAsync(AccountObject.Token, webSocketPackage.UploadId);

            if (file == null)
            {
                return;
            }

            if (file.Status == FileStatus.Synchronized)
            {
                file.Status = FileStatus.RemotelyMovedFrom;

                var newFile = await FileRepository.CloneAsync(file.Id);

                var newServerFile = await Connection.GetUploadInfoAsync(AccountObject.Token, webSocketPackage.UploadId);

                newFile.Name    = newServerFile.UploadList[0].Name;
                newFile.Status  = FileStatus.RemotelyMovedTo;
                newFile.MovedId = file.Id;
            }
            else
            {
                file.Status = FileStatus.Conflict;
            }
        }
Exemple #10
0
        private Task WebSocketMessageHandler(WebSocketSession session, WebSocketPackage package)
        {
            if (package.Message == null)
            {
                Console.WriteLine("Empty message");
                return(Task.CompletedTask);
            }

            var type = ExtensionMethods.GetXmlType(package.Message);

            if (type.HasValue)
            {
                switch (type)
                {
                case MrsMessageTypes.DeviceConfiguration:
                    return(HandleConfigRequest(session,
                                               ExtensionMethods.XmlConvert <DeviceConfiguration>(package.Message)));

                case MrsMessageTypes.DeviceSubscriptionConfiguration:
                    return(HandleSubscriptionRequest(ExtensionMethods.XmlConvert <DeviceSubscriptionConfiguration>(package.Message)));

                case MrsMessageTypes.CommandMessage:
                    return(HandleCommandMessage(ExtensionMethods.XmlConvert <CommandMessage>(package.Message)));
                }
            }
            else
            {
                Console.WriteLine("Unknown Message Type");
            }

            return(Task.CompletedTask);
        }
Exemple #11
0
        public override bool Process(WebSocketPackage package, ref SequenceReader <byte> reader, out IDataFramePartReader nextPartReader, out bool needMoreData)
        {
            nextPartReader = null;

            long required = package.PayloadLength;

            if (reader.Length < required)
            {
                needMoreData = true;
                return(false);
            }

            needMoreData = false;

            var seq = reader.Sequence.Slice(0, required);

            if (package.OpCode == OpCode.Binary)
            {
                package.Data = seq;
            }
            else
            {
                package.Message = seq.GetString(Encoding.UTF8);
            }

            reader.Advance(required);

            return(true);
        }
Exemple #12
0
        public void Encode(WebSocketPackage package)
        {
            package.RSV1 = true;

            if (package.Data.IsEmpty)
            {
                EncodeTextMessage(package);
            }
            else
            {
                EncodeDataMessage(package);
            }
        }
        public override bool Process(WebSocketPackage package, object filterContext, ref SequenceReader <byte> reader, out IPackagePartReader <WebSocketPackage> nextPartReader, out bool needMoreData)
        {
            if (reader.Length < 2)
            {
                nextPartReader = null;
                needMoreData   = true;
                return(false);
            }

            needMoreData = false;

            reader.TryRead(out byte firstByte);

            var opCode = (OpCode)(firstByte & 0x0f);

            if (opCode != OpCode.Continuation)
            {
                package.OpCode = opCode;
            }

            package.OpCodeByte = firstByte;

            reader.TryRead(out byte secondByte);
            package.PayloadLength = secondByte & 0x7f;
            package.HasMask       = (secondByte & 0x80) == 0x80;

            if (package.PayloadLength >= 126)
            {
                nextPartReader = ExtendedLengthReader;
            }
            else
            {
                if (package.HasMask)
                {
                    nextPartReader = MaskKeyReader;
                }
                else
                {
                    if (TryInitIfEmptyMessage(package))
                    {
                        nextPartReader = null;
                        return(true);
                    }

                    nextPartReader = PayloadDataReader;
                }
            }

            return(false);
        }
Exemple #14
0
        public override bool Process(WebSocketPackage package, ref SequenceReader <byte> reader, out IDataFramePartReader nextPartReader)
        {
            long required = package.PayloadLength;

            if (reader.Length < required)
            {
                nextPartReader = this;
                return(false);
            }

            package.Data   = reader.Sequence;
            nextPartReader = null;
            return(true);
        }
        public override bool Process(WebSocketPackage package, ref SequenceReader <byte> reader, out IDataFramePartReader nextPartReader)
        {
            int required = 4;

            if (reader.Length < required)
            {
                nextPartReader = this;
                return(false);
            }

            package.MaskKey = reader.Sequence.Slice(0, 4).ToArray();
            reader.Advance(4);

            nextPartReader = PayloadDataReader;
            return(false);
        }
        public override bool Process(WebSocketPackage package, ref SequenceReader <byte> reader, out IDataFramePartReader nextPartReader, out bool needMoreData)
        {
            nextPartReader = null;

            long required = package.PayloadLength;

            if (reader.Length < required)
            {
                needMoreData = true;
                return(false);
            }

            needMoreData = false;
            package.Data = reader.Sequence.Slice(0, required);
            reader.Advance(required);

            return(true);
        }
        public override bool Process(WebSocketPackage package, ref SequenceReader <byte> reader, out IDataFramePartReader nextPartReader, out bool needMoreData)
        {
            if (reader.Length < 2)
            {
                nextPartReader = null;
                needMoreData   = true;
                return(false);
            }

            needMoreData = false;

            reader.TryRead(out byte firstByte);
            package.OpCode     = (OpCode)(firstByte & 0x0f);
            package.OpCodeByte = firstByte;

            reader.TryRead(out byte secondByte);
            package.PayloadLength = secondByte & 0x7f;
            package.HasMask       = (secondByte & 0x80) == 0x80;

            if (package.PayloadLength >= 126)
            {
                nextPartReader = ExtendedLenghtReader;
            }
            else
            {
                if (package.HasMask)
                {
                    nextPartReader = MaskKeyReader;
                }
                else
                {
                    // no body
                    if (package.PayloadLength == 0)
                    {
                        nextPartReader = null;
                        return(true);
                    }

                    nextPartReader = PayloadDataReader;
                }
            }

            return(false);
        }
Exemple #18
0
        public override bool Process(WebSocketPackage package, ref SequenceReader <byte> reader, out IPackagePartReader <WebSocketPackage> nextPartReader, out bool needMoreData)
        {
            int required;

            if (package.PayloadLength == 126)
            {
                required = 2;
            }
            else
            {
                required = 8;
            }

            if (reader.Remaining < required)
            {
                nextPartReader = null;
                needMoreData   = true;
                return(false);
            }

            needMoreData = false;

            if (required == 2)
            {
                reader.TryReadBigEndian(out short len);
                package.PayloadLength = len;
            }
            else // required == 8 (long)
            {
                reader.TryReadBigEndian(out long len);
                package.PayloadLength = len;
            }

            if (package.HasMask)
            {
                nextPartReader = MaskKeyReader;
            }
            else
            {
                nextPartReader = PayloadDataReader;
            }

            return(false);
        }
        public override bool Process(WebSocketPackage package, ref SequenceReader <byte> reader, out IDataFramePartReader nextPartReader, out bool needMoreData)
        {
            int required = 4;

            if (reader.Remaining < required)
            {
                nextPartReader = null;
                needMoreData   = true;
                return(false);
            }

            needMoreData = false;

            package.MaskKey = reader.Sequence.Slice(reader.Consumed, 4).ToArray();
            reader.Advance(4);

            nextPartReader = PayloadDataReader;
            return(false);
        }
Exemple #20
0
        private void EncodeDataMessage(WebSocketPackage package)
        {
            var data = package.Data;

            RemoveLastFourOctets(ref data);

            var outputStream = new WritableSequenceStream();

            using (var stream = new DeflateStream(outputStream, CompressionMode.Compress))
            {
                foreach (var piece in data)
                {
                    stream.Write(piece.Span);
                }

                stream.Flush();
            }

            package.Data = outputStream.GetUnderlyingSequence();
        }
Exemple #21
0
        public override bool Process(WebSocketPackage package, ref SequenceReader <byte> reader, out IDataFramePartReader nextPartReader)
        {
            int required;

            if (package.PayloadLength == 126)
            {
                required = 2;
            }
            else
            {
                required = 8;
            }

            if (reader.Length < required)
            {
                nextPartReader = this;
                return(false);
            }

            if (required == 2)
            {
                reader.TryReadLittleEndian(out short len);
                package.PayloadLength = len;
            }
            else // required == 8 (long)
            {
                reader.TryReadLittleEndian(out long len);
                package.PayloadLength = len;
            }

            if (package.HasMask)
            {
                nextPartReader = MaskKeyReader;
            }
            else
            {
                nextPartReader = PayloadDataReader;
            }

            return(false);
        }
Exemple #22
0
        public void Decode(WebSocketPackage package)
        {
            if (!package.RSV1)
            {
                return;
            }

            var data = package.Data;

            data = data.ConcatSequence(new SequenceSegment(LAST_FOUR_OCTETS_REVERSE, LAST_FOUR_OCTETS_REVERSE.Length, false));

            SequenceSegment head = null;
            SequenceSegment tail = null;

            using (var stream = new DeflateStream(new ReadOnlySequenceStream(data), CompressionMode.Decompress))
            {
                while (true)
                {
                    var buffer = _arrayPool.Rent(_deflateBufferSize);
                    var read   = stream.Read(buffer, 0, buffer.Length);

                    if (read == 0)
                    {
                        break;
                    }

                    var segment = new SequenceSegment(buffer, read);

                    if (head == null)
                    {
                        tail = head = segment;
                    }
                    else
                    {
                        tail.SetNext(segment);
                    }
                }
            }

            package.Data = new ReadOnlySequence <byte>(head, 0, tail, tail.Memory.Length);
        }
Exemple #23
0
 public abstract bool Process(WebSocketPackage package, ref SequenceReader <byte> reader, out IDataFramePartReader nextPartReader, out bool needMoreData);
        /// <summary>
        /// 有效负载数据读取过程
        /// </summary>
        /// <param name="package">WebSocet包</param>
        /// <param name="filterContext">筛选器上下文</param>
        /// <param name="reader">序列阅读器</param>
        /// <param name="nextPartReader">下一分件阅读器</param>
        /// <param name="needMoreData">需要更多数据</param>
        /// <returns></returns>
        public override bool Process(WebSocketPackage package, object filterContext, ref SequenceReader <byte> reader, out IPackagePartReader <WebSocketPackage> nextPartReader, out bool needMoreData)
        {
            nextPartReader = null;

            long required = package.PayloadLength;

            if (reader.Remaining < required)
            {
                needMoreData = true;
                return(false);
            }

            needMoreData = false;

            var seq = reader.Sequence.Slice(reader.Consumed, required);

            if (package.HasMask)
            {
                DecodeMask(ref seq, package.MaskKey);
            }

            try
            {
                // single fragment
                if (package.FIN && package.Head == null)
                {
                    package.Data = seq;
                }
                else
                {
                    package.ConcatSequence(ref seq);
                }

                if (package.FIN)
                {
                    if (package.Head != null)
                    {
                        package.BuildData();
                    }

                    var websocketFilterContext = filterContext as WebSocketPipelineFilterContext;

                    if (websocketFilterContext != null && websocketFilterContext.Extensions != null && websocketFilterContext.Extensions.Count > 0)
                    {
                        foreach (var extension in websocketFilterContext.Extensions)
                        {
                            try
                            {
                                extension.Decode(package);
                            }
                            catch (Exception e)
                            {
                                throw new Exception($"Problem happened when decode with the extension {extension.Name}.", e);
                            }
                        }
                    }

                    var data = package.Data;

                    if (package.OpCode == OpCode.Text)
                    {
                        package.Message = data.GetString(Encoding.UTF8);
                        package.Data    = default;
                    }
                    else
                    {
                        package.Data = data.CopySequence();
                    }

                    return(true);
                }
                else
                {
                    // start to process next fragment
                    nextPartReader = FixPartReader;
                    return(false);
                }
            }
            finally
            {
                reader.Advance(required);
            }
        }
Exemple #25
0
 public virtual ValueTask SendAsync(WebSocketPackage message)
 {
     return(this.Channel.SendAsync(MessageEncoder, message));
 }
Exemple #26
0
 internal RemoteFileScanObjectCommand(IFileRepository repository, IConnection connection, SynchronizationObject accountObject, WebSocketPackage webSocketPackage)
     : base(repository, connection, accountObject)
 {
     _webSocketPackage = webSocketPackage;
 }
 /// <summary>
 /// 处理
 /// </summary>
 /// <param name="session">Session</param>
 /// <param name="package">WebSocket包</param>
 /// <returns></returns>
 public override async ValueTask Handle(IAppSession session, WebSocketPackage package)
 {
     await _packageHandler(session as WebSocketSession, package);
 }
Exemple #28
0
        private async Task ProcessCreated(WebSocketPackage webSocketPackage)
        {
            var file = await FileRepository.FindAsync(AccountObject.Token, webSocketPackage.UploadId);

            if (file != null)
            {
                return;
            }

            var remoteFile = await Connection.GetUploadInfoAsync(AccountObject.Token, webSocketPackage.UploadId);

            if (remoteFile == null || remoteFile.UploadList.Length == 0)
            {
                return;
            }

            file = new FileEntity
            {
                UploadId = webSocketPackage.UploadId,
                Crc32    = remoteFile.UploadList[0].Crc32,
                Size     = remoteFile.UploadList[0].Size,
                IsFolder = remoteFile.UploadList[0].IsFolder,
                Name     = remoteFile.UploadList[0].Name,
                Token    = AccountObject.Token,
                Status   = FileStatus.RemotelyCreated
            };

            if (webSocketPackage.FolderId.HasValue && webSocketPackage.FolderId != 0)
            {
                var remoteParent = await FileRepository.FindAsync(AccountObject.Token, webSocketPackage.FolderId);

                if (remoteParent == null)
                {
                    //there is no parent folder in the DB, let's wait for another iteration
                    PackagesBuffer.Add(webSocketPackage);
                    return;
                }

                file.ParentId = remoteParent.Id;
            }

            var oldFile = await FileRepository.FindAsync(file);

            if (oldFile != null)
            {
                if (file.UploadId == oldFile.UploadId)
                {
                    //the same file scanned twice, should never happened, but who knows
                    oldFile.Status = FileStatus.Conflict;
                    return;
                }

                file.Name = await GetIncrementName(file);

                file.Status = FileStatus.RenameRequired;
                await FileRepository.AddAsync(file);
            }
            else
            {
                //detect moved files
                var deleted = await FileRepository.FindAsync(x =>
                                                             x.Size == file.Size &&
                                                             x.Status == FileStatus.RemotelyDeleted &&
                                                             x.Name == file.Name &&
                                                             x.Crc32 == file.Crc32 &&
                                                             x.UploadId != file.UploadId);

                if (deleted != null)
                {
                    deleted.Status  = FileStatus.RemotelyMovedFrom;
                    deleted.MovedId = file.Id;
                    file.Status     = FileStatus.RemotelyMovedTo;
                    file.MovedId    = file.Id;
                }
                else
                {
                    file.Status = FileStatus.RemotelyCreated;
                }

                await FileRepository.AddAsync(file);
            }
        }
Exemple #29
0
 /// <summary>
 /// 处理
 /// </summary>
 /// <param name="session">Session</param>
 /// <param name="package">WebSocket包</param>
 /// <returns></returns>
 public abstract ValueTask Handle(IAppSession session, WebSocketPackage package);
Exemple #30
0
 internal ValueTask OnPongReceived(WebSocketPackage pong)
 {
     _pongReceivedTaskSource.SetResult(pong);
     return(new ValueTask());
 }