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); } }
internal async ValueTask OnPingReceived(WebSocketPackage ping) { ping.OpCode = OpCode.Pong; await WebSocket.SendAsync(ping); LastPingReceived = DateTimeOffset.Now; }
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); }
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; }
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); }
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); }
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)); }
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(); }
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; } }
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); }
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); }
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); }
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); }
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); }
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(); }
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); }
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); }
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); } }
public virtual ValueTask SendAsync(WebSocketPackage message) { return(this.Channel.SendAsync(MessageEncoder, message)); }
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); }
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); } }
/// <summary> /// 处理 /// </summary> /// <param name="session">Session</param> /// <param name="package">WebSocket包</param> /// <returns></returns> public abstract ValueTask Handle(IAppSession session, WebSocketPackage package);
internal ValueTask OnPongReceived(WebSocketPackage pong) { _pongReceivedTaskSource.SetResult(pong); return(new ValueTask()); }