Example #1
0
        private void Action <TArgument>(AmoebaRequestType type, TArgument argument, CancellationToken token)
        {
            var(id, queue) = this.Send(type, argument);

            using (var register = token.Register(() => this.Cancel(id)))
            {
                ResponseInfo info = null;

                try
                {
                    info = queue.Dequeue();

                    if (info.Type == AmoebaResponseType.Result)
                    {
                        return;
                    }
                    else if (info.Type == AmoebaResponseType.Error)
                    {
                        throw new AmoebaInterfaceManagerException(JsonUtils.Load <string>(info.Stream));
                    }

                    throw new NotSupportedException();
                }
                finally
                {
                    queue.Dispose();
                    _queueMap.Remove(id);

                    if (info != null)
                    {
                        info.Stream.Dispose();
                    }
                }
            }
        }
Example #2
0
        public static T Clone <T>(T item)
        {
            using (var stream = new BufferStream(BufferManager.Instance))
            {
                JsonUtils.Save(stream, item);
                stream.Seek(0, SeekOrigin.Begin);

                return(JsonUtils.Load <T>(stream));
            }
        }
Example #3
0
        private void Action <TArgument, TProgress>(AmoebaFunctionType type, TArgument argument, Action <TProgress> progress, CancellationToken token)
        {
            var(id, queue) = this.Send(type, argument);

            try
            {
                using (var register = token.Register(() => this.Cancel(id)))
                {
                    for (; ;)
                    {
                        var info = queue.Dequeue();

                        try
                        {
                            if (info.Type == AmoebaFunctionResponseType.Result)
                            {
                                return;
                            }
                            else if (info.Type == AmoebaFunctionResponseType.Output)
                            {
                                progress.Invoke(JsonUtils.Load <TProgress>(info.Stream));
                            }
                            else if (info.Type == AmoebaFunctionResponseType.Cancel)
                            {
                                throw new OperationCanceledException();
                            }
                            else if (info.Type == AmoebaFunctionResponseType.Error)
                            {
                                throw new AmoebaInterfaceManagerException(JsonUtils.Load <AmoebaErrorMessage>(info.Stream));
                            }
                            else
                            {
                                throw new NotSupportedException();
                            }
                        }
                        finally
                        {
                            info.Stream.Dispose();
                        }
                    }
                }
            }
            finally
            {
                queue.Dispose();
                _queueMap.Remove(id);
            }
        }
        private void _messagingManager_ReceiveEvent(Stream requestStream)
        {
            var reader = new MessageStreamReader(new WrapperStream(requestStream), _bufferManager);

            {
                var type = (AmoebaFunctionType)reader.GetUInt64();
                int id   = (int)reader.GetUInt64();

                if (type == AmoebaFunctionType.Exit)
                {
                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                    _tokenSource.Cancel();
                }
                else if (type == AmoebaFunctionType.Cancel)
                {
                    if (_tasks.TryGetValue(id, out var responseTask))
                    {
                        responseTask.Stop();
                    }
                }
                else
                {
                    var responseTask = ResponseTask.Create((token) =>
                    {
                        try
                        {
                            switch (type)
                            {
                            case AmoebaFunctionType.GetReport:
                                {
                                    SendResponse(AmoebaFunctionResponseType.Result, id, _serviceManager.Report);
                                    break;
                                }

                            case AmoebaFunctionType.GetNetworkConnectionReports:
                                {
                                    SendResponse(AmoebaFunctionResponseType.Result, id, _serviceManager.GetNetworkConnectionReports());
                                    break;
                                }

                            case AmoebaFunctionType.GetCacheContentReports:
                                {
                                    SendResponse(AmoebaFunctionResponseType.Result, id, _serviceManager.GetCacheContentReports());
                                    break;
                                }

                            case AmoebaFunctionType.GetDownloadContentReports:
                                {
                                    SendResponse(AmoebaFunctionResponseType.Result, id, _serviceManager.GetDownloadContentReports());
                                    break;
                                }

                            case AmoebaFunctionType.GetConfig:
                                {
                                    SendResponse(AmoebaFunctionResponseType.Result, id, _serviceManager.Config);
                                    break;
                                }

                            case AmoebaFunctionType.SetConfig:
                                {
                                    var config = JsonUtils.Load <ServiceConfig>(requestStream);
                                    _serviceManager.SetConfig(config);
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.SetCloudLocations:
                                {
                                    var cloudLocations = JsonUtils.Load <Location[]>(requestStream);
                                    _serviceManager.SetCloudLocations(cloudLocations);
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.GetSize:
                                {
                                    SendResponse(AmoebaFunctionResponseType.Result, id, _serviceManager.Size);
                                    break;
                                }

                            case AmoebaFunctionType.Resize:
                                {
                                    long size = JsonUtils.Load <long>(requestStream);
                                    _serviceManager.Resize(size);
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.CheckBlocks:
                                {
                                    _serviceManager.CheckBlocks(new Action <CheckBlocksProgressReport>((report) =>
                                    {
                                        SendResponse(AmoebaFunctionResponseType.Output, id, report);
                                    }), token).Wait();

                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.AddContent:
                                {
                                    var arguments = JsonUtils.Load <(string, DateTime)>(requestStream);
                                    var result    = _serviceManager.AddContent(arguments.Item1, arguments.Item2, token).Result;
                                    SendResponse(AmoebaFunctionResponseType.Result, id, result);
                                    break;
                                }

                            case AmoebaFunctionType.RemoveContent:
                                {
                                    string path = JsonUtils.Load <string>(requestStream);
                                    _serviceManager.RemoveContent(path);
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.Diffusion:
                                {
                                    string path = JsonUtils.Load <string>(requestStream);
                                    _serviceManager.DiffuseContent(path);
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.AddDownload:
                                {
                                    var arguments = JsonUtils.Load <(Metadata, string, long)>(requestStream);
                                    _serviceManager.AddDownload(arguments.Item1, arguments.Item2, arguments.Item3);
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.RemoveDownload:
                                {
                                    var arguments = JsonUtils.Load <(Metadata, string)>(requestStream);
                                    _serviceManager.RemoveDownload(arguments.Item1, arguments.Item2);
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.ResetDownload:
                                {
                                    var arguments = JsonUtils.Load <(Metadata, string)>(requestStream);
                                    _serviceManager.ResetDownload(arguments.Item1, arguments.Item2);
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.SetProfile:
                                {
                                    var arguments = JsonUtils.Load <(ProfileContent, DigitalSignature)>(requestStream);
                                    _serviceManager.SetProfile(arguments.Item1, arguments.Item2, token).Wait();
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.SetStore:
                                {
                                    var arguments = JsonUtils.Load <(StoreContent, DigitalSignature)>(requestStream);
                                    _serviceManager.SetStore(arguments.Item1, arguments.Item2, token).Wait();
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.SetUnicastCommentMessage:
                                {
                                    var arguments = JsonUtils.Load <(Signature, CommentContent, AgreementPublicKey, DigitalSignature)>(requestStream);
                                    _serviceManager.SetUnicastCommentMessage(arguments.Item1, arguments.Item2, arguments.Item3, arguments.Item4, token).Wait();
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.SetMulticastCommentMessage:
                                {
                                    var arguments = JsonUtils.Load <(Tag, CommentContent, DigitalSignature, TimeSpan)>(requestStream);
                                    _serviceManager.SetMulticastCommentMessage(arguments.Item1, arguments.Item2, arguments.Item3, arguments.Item4, token).Wait();
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.GetProfile:
                                {
                                    var signature = JsonUtils.Load <Signature>(requestStream);
                                    var result    = _serviceManager.GetProfile(signature, token).Result;
                                    SendResponse(AmoebaFunctionResponseType.Result, id, result);
                                    break;
                                }

                            case AmoebaFunctionType.GetStore:
                                {
                                    var signature = JsonUtils.Load <Signature>(requestStream);
                                    var result    = _serviceManager.GetStore(signature, token).Result;
                                    SendResponse(AmoebaFunctionResponseType.Result, id, result);
                                    break;
                                }

                            case AmoebaFunctionType.GetUnicastCommentMessages:
                                {
                                    var arguments = JsonUtils.Load <(Signature, AgreementPrivateKey)>(requestStream);
                                    var result    = _serviceManager.GetUnicastCommentMessages(arguments.Item1, arguments.Item2, token).Result;
                                    SendResponse(AmoebaFunctionResponseType.Result, id, result);
                                    break;
                                }

                            case AmoebaFunctionType.GetMulticastCommentMessages:
                                {
                                    var tag    = JsonUtils.Load <Tag>(requestStream);
                                    var result = _serviceManager.GetMulticastCommentMessages(tag, token).Result;
                                    SendResponse(AmoebaFunctionResponseType.Result, id, result);
                                    break;
                                }

                            case AmoebaFunctionType.GetState:
                                {
                                    SendResponse(AmoebaFunctionResponseType.Result, id, _serviceManager.State);
                                    break;
                                }

                            case AmoebaFunctionType.Start:
                                {
                                    _serviceManager.Start();
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.Stop:
                                {
                                    _serviceManager.Stop();
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.Load:
                                {
                                    _serviceManager.Load();
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.Save:
                                {
                                    _serviceManager.Save();
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }
                            }
                        }
                        catch (OperationCanceledException)
                        {
                            SendResponse(AmoebaFunctionResponseType.Cancel, id, (object)null);
                        }
                        catch (Exception e)
                        {
                            Log.Error(string.Format("Rpc Error: {0}", type.ToString()));
                            Log.Error(e);

                            var argument = new AmoebaErrorMessage(e.GetType().ToString(), e.Message, e.StackTrace?.ToString());
                            SendResponse(AmoebaFunctionResponseType.Error, id, argument);
                        }
                        finally
                        {
                            requestStream.Dispose();
                            _tasks.Remove(id);
                        }
                    });

                    _tasks.Add(id, responseTask);
                    responseTask.Start();
                }
            }

            void SendResponse <T>(AmoebaFunctionResponseType type, int id, T value)
            {
                var messageStream = new RecyclableMemoryStream(_bufferManager);
                var writer        = new MessageStreamWriter(messageStream, _bufferManager);

                writer.Write((ulong)type);
                writer.Write((ulong)id);

                Stream valueStream = null;

                if (value != null)
                {
                    try
                    {
                        valueStream = new RecyclableMemoryStream(_bufferManager);
                        JsonUtils.Save(valueStream, value);
                    }
                    catch (Exception)
                    {
                        if (valueStream != null)
                        {
                            valueStream.Dispose();
                            valueStream = null;
                        }

                        return;
                    }
                }

                messageStream.Seek(0, SeekOrigin.Begin);
                _messagingManager.Send(new UniteStream(messageStream, valueStream));
            }
        }
        private void MessagingManager_ReceiveEvent <TService>(TService serviceManager, Stream requestStream, Action <Stream> sendAction, Action exitAction)
            where TService : StateManagerBase, IService
        {
            using (var reader = new ItemStreamReader(new WrapperStream(requestStream, true), _bufferManager))
            {
                var type = (AmoebaRequestType)reader.GetUInt32();
                int id   = (int)reader.GetUInt32();

                if (type == AmoebaRequestType.Exit)
                {
                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                    exitAction();
                }
                else if (type == AmoebaRequestType.Cancel)
                {
                    if (_tasks.TryGetValue(id, out var responseTask))
                    {
                        responseTask.Stop();
                    }
                }
                else
                {
                    var responseTask = ResponseTask.Create((token) =>
                    {
                        try
                        {
                            switch (type)
                            {
                            case AmoebaRequestType.GetState:
                                {
                                    SendResponse(AmoebaResponseType.Result, id, serviceManager.State);
                                    break;
                                }

                            case AmoebaRequestType.Start:
                                {
                                    serviceManager.Start();
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.Stop:
                                {
                                    serviceManager.Stop();
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.GetReport:
                                {
                                    SendResponse(AmoebaResponseType.Result, id, serviceManager.Report);
                                    break;
                                }

                            case AmoebaRequestType.GetNetworkConnectionReports:
                                {
                                    SendResponse(AmoebaResponseType.Result, id, serviceManager.GetNetworkConnectionReports());
                                    break;
                                }

                            case AmoebaRequestType.GetCacheContentReports:
                                {
                                    SendResponse(AmoebaResponseType.Result, id, serviceManager.GetCacheContentReports());
                                    break;
                                }

                            case AmoebaRequestType.GetDownloadContentReports:
                                {
                                    SendResponse(AmoebaResponseType.Result, id, serviceManager.GetDownloadContentReports());
                                    break;
                                }

                            case AmoebaRequestType.GetConfig:
                                {
                                    SendResponse(AmoebaResponseType.Result, id, serviceManager.Config);
                                    break;
                                }

                            case AmoebaRequestType.SetConfig:
                                {
                                    var config = JsonUtils.Load <ServiceConfig>(requestStream);
                                    serviceManager.SetConfig(config);
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.SetCloudLocations:
                                {
                                    var cloudLocations = JsonUtils.Load <Location[]>(requestStream);
                                    serviceManager.SetCloudLocations(cloudLocations);
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.GetSize:
                                {
                                    SendResponse(AmoebaResponseType.Result, id, serviceManager.Size);
                                    break;
                                }

                            case AmoebaRequestType.Resize:
                                {
                                    long size = JsonUtils.Load <long>(requestStream);
                                    serviceManager.Resize(size);
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.CheckBlocks:
                                {
                                    try
                                    {
                                        serviceManager.CheckBlocks(new Progress <CheckBlocksProgressReport>((report) =>
                                        {
                                            SendResponse(AmoebaResponseType.Output, id, report);
                                        }), token).Wait();
                                    }
                                    catch (Exception)
                                    {
                                    }

                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.AddContent:
                                {
                                    var arguments = JsonUtils.Load <(string, DateTime)>(requestStream);
                                    var result    = serviceManager.AddContent(arguments.Item1, arguments.Item2, token).Result;
                                    SendResponse(AmoebaResponseType.Result, id, result);
                                    break;
                                }

                            case AmoebaRequestType.RemoveContent:
                                {
                                    string path = JsonUtils.Load <string>(requestStream);
                                    serviceManager.RemoveContent(path);
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.Diffusion:
                                {
                                    string path = JsonUtils.Load <string>(requestStream);
                                    serviceManager.Diffusion(path);
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.AddDownload:
                                {
                                    var arguments = JsonUtils.Load <(Metadata, string, long)>(requestStream);
                                    serviceManager.AddDownload(arguments.Item1, arguments.Item2, arguments.Item3);
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.RemoveDownload:
                                {
                                    var arguments = JsonUtils.Load <(Metadata, string)>(requestStream);
                                    serviceManager.RemoveDownload(arguments.Item1, arguments.Item2);
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.ResetDownload:
                                {
                                    var arguments = JsonUtils.Load <(Metadata, string)>(requestStream);
                                    serviceManager.ResetDownload(arguments.Item1, arguments.Item2);
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.SetProfile:
                                {
                                    var arguments = JsonUtils.Load <(Profile, DigitalSignature)>(requestStream);
                                    serviceManager.SetProfile(arguments.Item1, arguments.Item2, token).Wait();
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.SetStore:
                                {
                                    var arguments = JsonUtils.Load <(Store, DigitalSignature)>(requestStream);
                                    serviceManager.SetStore(arguments.Item1, arguments.Item2, token).Wait();
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.SetMailMessage:
                                {
                                    var arguments = JsonUtils.Load <(Signature, MailMessage, ExchangePublicKey, DigitalSignature)>(requestStream);
                                    serviceManager.SetMailMessage(arguments.Item1, arguments.Item2, arguments.Item3, arguments.Item4, token).Wait();
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.SetChatMessage:
                                {
                                    var arguments = JsonUtils.Load <(Tag, ChatMessage, DigitalSignature, TimeSpan)>(requestStream);
                                    serviceManager.SetChatMessage(arguments.Item1, arguments.Item2, arguments.Item3, arguments.Item4, token).Wait();
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.GetProfile:
                                {
                                    var signature = JsonUtils.Load <Signature>(requestStream);
                                    var result    = serviceManager.GetProfile(signature, token).Result;
                                    SendResponse(AmoebaResponseType.Result, id, result);
                                    break;
                                }

                            case AmoebaRequestType.GetStore:
                                {
                                    var signature = JsonUtils.Load <Signature>(requestStream);
                                    var result    = serviceManager.GetStore(signature, token).Result;
                                    SendResponse(AmoebaResponseType.Result, id, result);
                                    break;
                                }

                            case AmoebaRequestType.GetMailMessages:
                                {
                                    var arguments = JsonUtils.Load <(Signature, ExchangePrivateKey)>(requestStream);
                                    var result    = serviceManager.GetMailMessages(arguments.Item1, arguments.Item2, token).Result;
                                    SendResponse(AmoebaResponseType.Result, id, result);
                                    break;
                                }

                            case AmoebaRequestType.GetChatMessages:
                                {
                                    var tag    = JsonUtils.Load <Tag>(requestStream);
                                    var result = serviceManager.GetChatMessages(tag, token).Result;
                                    SendResponse(AmoebaResponseType.Result, id, result);
                                    break;
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            SendResponse(AmoebaResponseType.Error, id, e.Message);
                        }
                        finally
                        {
                            _tasks.Remove(id);
                        }
                    });

                    _tasks.Add(id, responseTask);
                    responseTask.Start();
                }
            }

            void SendResponse <T>(AmoebaResponseType type, int id, T value)
            {
                using (var writer = new ItemStreamWriter(_bufferManager))
                {
                    writer.Write((uint)type);
                    writer.Write((uint)id);

                    Stream valueStream = null;

                    if (value != null)
                    {
                        try
                        {
                            valueStream = new BufferStream(_bufferManager);
                            JsonUtils.Save(valueStream, value);
                        }
                        catch (Exception)
                        {
                            if (valueStream != null)
                            {
                                valueStream.Dispose();
                                valueStream = null;
                            }

                            return;
                        }
                    }

                    sendAction(new UniteStream(writer.GetStream(), valueStream));
                }
            }
        }