Beispiel #1
0
 public void EnqueueCommand(string clientID, RpcCommand command)
 {
     lock (syncLock) {
         var dir = GetDirectory(clientID);
         // Apply strategy
         var strategy = command.RetryStrategy;
         if (strategy == null || strategy == RpcRetryStrategy.None)
         {
             // No retry strategy chosen. This method should not have been called at all. Do nothing.
             return;
         }
         else if (strategy == RpcRetryStrategy.RetryWhenOnline)
         {
             // No preparation needed; just enqueue this command
         }
         else if (strategy == RpcRetryStrategy.RetryNewestWhenOnline)
         {
             // Remove all preceding commands of this type
             foreach (var file in GetFilesByCommandName(clientID, command.MethodName))
             {
                 file.Delete();
             }
         }
         var filename = command.ID + "-" + command.MethodName;
         File.WriteAllText(Path.Combine(dir.FullName, filename), JsonLib.ToJson(command));
     }
 }
Beispiel #2
0
        /// <summary>
        /// Call this method when the client called the "/rpc/push"-endpoint.
        /// It executes the given RPC command immediately and returns the result.
        /// No exception is thrown, but a <see cref="RpcFailure"/> result is set in case of a failure.
        /// </summary>
        public async Task <RpcCommandResult> OnClientPush(string clientID, RpcCommand command, RpcCommandRunner runner)
        {
            // Do not run the same command twice. If the command with this ID was already
            // executed, return the cached result. If the cache is not available any more, return a
            // obsolete function call failure.
            var client = clients.GetClient(clientID, commandBacklog);

            if (client.GetCachedResult(command.ID) is RpcCommandResult result)
            {
                return(result);
            }
            // Execute the command
            try {
                result = await runner.Execute(clientID, command);
            }
            catch (Exception ex) {
                result = RpcCommandResult.FromFailure(command.ID,
                                                      new RpcFailure(RpcFailureType.RemoteException, ex.Message));
            }
            // Cache result, if there was no network problem
            if (false == (result.Failure?.IsNetworkProblem == true))
            {
                client.CacheResult(result);
            }
            return(result);
        }
Beispiel #3
0
 /// <summary>
 /// Executes the given RPC command locally on the client immediately and returns the result.
 /// No exception is thrown, but a <see cref="RpcFailure"/> result is set in case of a failure.
 /// </summary>
 public async Task <RpcCommandResult> ExecuteLocallyNow(RpcCommand command)
 {
     // Do not run the same command twice. If the command with this ID was already
     // executed, return the cached result. If the cache is not available any more, return a
     // obsolete function call failure.
     if (serverCache.GetCachedResult(command.ID) is RpcCommandResult result)
     {
         return(result);
     }
     // Execute the command
     try {
         var runner = new RpcCommandRunner(clientMethods(), null);
         result = await runner.Execute(clientConfig.ClientID, command);
     }
     catch (Exception ex) {
         result = RpcCommandResult.FromFailure(command.ID,
                                               new RpcFailure(RpcFailureType.RemoteException, ex.Message));
     }
     // Cache result, if there was no network problem
     if (false == (result.Failure?.IsNetworkProblem == true))
     {
         serverCache.CacheResult(result);
     }
     return(result);
 }
Beispiel #4
0
        static async Task <string> LoadSharedImage(HttpClient client, string rpcUri)
        {
            var imageName = "image-1";        // 共享图像名
            var fmt       = "rgb24";          // 图像像素格式
            var w         = 2048;             // 图像宽度
            var h         = 1024;             // 图像高度
            var channels  = 3;                // 图像颜色通道数
            var bytes     = w * h * channels; // 图像字节数

            using (var mapFile = System.IO.MemoryMappedFiles.MemoryMappedFile.CreateNew(imageName, bytes))
                using (var accessor = mapFile.CreateViewAccessor())
                {
                    // 生成图像
                    for (var y = 0; y < h; ++y)
                    {
                        for (var x = 0; x < w; ++x)
                        {
                            var i = ((y * w) + x) * 3;
                            var r = (x % w) * 256 / w;
                            var g = (y % h) * 256 / h;
                            accessor.Write(i + 0, (byte)r);
                            accessor.Write(i + 1, (byte)g);
                            accessor.Write(i + 2, (byte)0);
                        }
                    }

                    var data = new byte[bytes];
                    accessor.ReadArray(0, data, 0, data.Length);

                    // 构建远程过程调用命令
                    var cmds = new RpcCommand[] {
                        new RpcCommandWithId
                        {
                            id      = 1,
                            method  = "load_shared_image",
                            @params = new object[] { imageName, fmt, w, h },
                        },
                        new RpcCommandWithId
                        {
                            id      = 2,
                            method  = "inspect",
                            @params = new object[0],
                        },
                        new RpcCommand
                        {
                            method  = "zoom",
                            @params = new object[] { 0.5 },
                        },
                    };

                    // 远程过程调用
                    var json    = Newtonsoft.Json.JsonConvert.SerializeObject(cmds);
                    var content = new StringContent(json, Encoding.UTF8, "application/json-rpc");
                    var resp    = await client.PostAsync(rpcUri, content);

                    return(await resp.Content.ReadAsStringAsync());
                }
        }
Beispiel #5
0
        public static string GetCommandName(this RpcCommand command)
        {
            var attr = (DescriptionAttribute)command.GetType()
                       .GetCustomAttributes(typeof(DescriptionAttribute), false)
                       .FirstOrDefault();

            if (attr != null)
            {
                return(attr.Description);
            }

            return(null);
        }
Beispiel #6
0
        public async Task <string> Any(RpcCommand request)
        {
            var validation = CommandValidator.Validate(request);

            if (validation.Valid)
            {
                return(await PostRequest(request));
            }
            else
            {
                throw new HttpError(HttpStatusCode.BadRequest, validation.ErrorText);
            }
        }
Beispiel #7
0
 /// <summary>
 /// Runs the given command on the client ID.
 /// </summary>
 public async Task <RpcCommandResult> Execute(string clientID, RpcCommand command)
 {
     foreach (var rpc in rpcFunctions)
     {
         rpc.Context = new RpcContext(clientID, serviceScopeFactory);
         if (rpc.Execute(command) is Task <string?> task)
         {
             // Method found in this class
             return(RpcCommandResult.FromSuccess(command.ID, await task));
         }
     }
     // Called method is not implemented in any registered class
     throw new Exception("Unknown method name: " + command.MethodName);
 }
Beispiel #8
0
        private async Task <T> Post <T>(RpcMethod method, string[] parameters = null)
        {
            using (var client = new JsonServiceClient(baseUrl))
            {
                var command = new RpcCommand
                {
                    Method = method,
                    Params = parameters
                };
                var response = await client.PostAsync(command);

                var rpcresult = response.FromJson <RpcResult <T> >();
                return(rpcresult.result);
            }
        }
Beispiel #9
0
        /// <summary>
        /// Writes a command with arguments to the RPC pipe.
        /// </summary>
        /// <param name="command">The command to execute, from <see cref="Commands"/></param>
        /// <param name="arguments">The command arguments object, to be serialized as JSON</param>
        /// <returns>Task that resolves when the command has been sent</returns>
        public Task SendCommandAsync(string command, object arguments)
        {
            var frame = new RpcFrame();

            var cmd = new RpcCommand
            {
                Arguments = JObject.FromObject(arguments),
                Command   = command
            };

            frame.OpCode = OpCode.Frame;
            frame.SetContent(JsonConvert.SerializeObject(cmd));

            return(_pipe.WriteAsync(frame));
        }
        /// <summary>
        /// Dispatches a command with arguments to pipe.
        /// </summary>
        /// <param name="command">The command to execute</param>
        /// <param name="args"></param>
        public void DispatchCommand(RpcCommand command, object args = null)
        {
            var dispatch = new RpcDispatch();

            dispatch.Command   = command.GetCommandName();
            dispatch.Arguments = args;

            var packet = new RpcPacket();

            packet.OpCode = RpcOpCode.Frame;
            packet.SetData(dispatch.ToJson());

            rpc.RaiseLogEvent(this, LogLevel.Debug, $"Dispatching command {command.GetCommandName()}");
            Write(packet);
        }
Beispiel #11
0
        private async Task <string> PostRequest(RpcCommand request)
        {
            try
            {
                using (var client = new JsonHttpClient(VergeConfig.GetUri()))
                {
                    client.AddHeader("Authorization", VergeConfig.GetAuthHeaderValue());
                    var response = await client.PostAsync <string>(new Payload(request));

                    return(response);
                }
            }
            catch (Exception ex)
            {
                throw new HttpError(HttpStatusCode.InternalServerError, ex);
            }
        }
Beispiel #12
0
 public string Serialize(RpcCommand cmd)
 {
     ApiCommands.RpcCommand target = null;
     if (cmd is GameCmd)
     {
         if (cmd is CmdPlayerMove move)
         {
             target = new ApiCommands.CmdPlayerMove()
             {
                 current_pos = move.current_pos,
                 next_pos    = move.next_pos,
                 use_time    = move.use_time,
                 speed       = move.speed,
                 move_mode   = (byte)move.move_mode,
                 stamp       = move.stamp
             };
         }
         if (cmd is CmdPlayerStopMove stopMove)
         {
             target = new ApiCommands.CmdPlayerStopMove()
             {
                 current_pos = stopMove.current_pos,
                 speed       = stopMove.speed,
                 dir         = stopMove.dir,
                 move_mode   = (byte)stopMove.move_mode,
                 stamp       = stopMove.stamp,
                 use_time    = stopMove.use_time
             };
         }
         if (cmd is CmdReviveVillage)
         {
             target = new ApiCommands.CmdReviveVillage();
         }
         if (cmd is CmdGetAllData getAllData)
         {
             target = new ApiCommands.CmdGetAllData()
             {
                 include_equip_info = getAllData.include_equip_info,
                 include_pack_info  = getAllData.include_pack_info,
                 include_task_info  = getAllData.include_task_info
             };
         }
     }
     return(JsonConvert.SerializeObject(target.IntoRpc(), Formatting.None));
 }
Beispiel #13
0
        public frmMain()
        {
            InitializeComponent();
            var iniReader      = new IniReader(Resx.iniFileName);
            var config         = new SetupConfig();
            var rpcCommand     = new RpcCommand(config.GetKodiIP());
            var kodi           = new Kodi(rpcCommand);
            var yamahaCommand  = new YamahaCommand();
            var soapCommand    = new SoapCommand();
            var yamahaResponse = new YamahaResponse();
            var avReceiver     = new AVReceiver(yamahaCommand, soapCommand, yamahaResponse);

            mediator = new Mediator(kodi, avReceiver, iniReader);

            RegisterButtons();

            mediator.SetStripColors();
        }
Beispiel #14
0
 /// <summary>
 /// Enqueues the given command in the queue.
 /// When the queue would become too long, an <see cref="RpcException"/> of type
 /// <see cref="RpcFailureType.LocalQueueOverflow"/> is thrown.
 /// </summary>
 public void EnqueueCommand(RpcCommand command)
 {
     try {
         // When it is a command which should be retried in case of network failure, enqueue it in the command backlog.
         if (command.RetryStrategy != null && command.RetryStrategy != RpcRetryStrategy.None)
         {
             CommandBacklog.EnqueueCommand(ClientID, command);
         }
         // Always (additionally to the command backlog) add it to our normal query for immediate execution
         queue.Enqueue(command);
         command.SetState(RpcCommandState.Enqueued);
     }
     catch {
         throw new RpcException(new RpcFailure(
                                    RpcFailureType.QueueOverflow, $"Queue already full " +
                                    (ClientID != null ? $"for the client { ClientID}" : "for the server")));
     }
 }
Beispiel #15
0
 /// <summary>
 /// Runs the given RPC command on the server as soon as possible
 /// and returns the result or throws an <see cref="RpcException"/>.
 /// </summary>
 public async Task <T> ExecuteOnServer <T>(RpcCommand command)
 {
     try {
         // Apply [RpcOptions(...)] from method declaration
         command.ApplyRpcOptionsFromCallStack();
         // Enqueue (and execute)
         serverCache.EnqueueCommand(command);
         // Wait for result until timeout
         return(await command.WaitForResult <T>());
     }
     catch (RpcException ex) {
         // Rethrow RPC exception
         throw;
     }
     catch (Exception ex) {
         throw new RpcException(new RpcFailure(RpcFailureType.Other, ex.Message)); // Wrap any other exception
     }
 }
Beispiel #16
0
 //JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
 //ORIGINAL LINE: @SuppressWarnings({ "rawtypes", "unchecked" }) private void process(RemotingContext ctx, Object msg)
 private void process(RemotingContext ctx, object msg)
 {
     try
     {
         //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
         //ORIGINAL LINE: final rpc.RpcCommand cmd = (rpc.RpcCommand) msg;
         RpcCommand cmd = (RpcCommand)msg;
         //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
         //ORIGINAL LINE: final RemotingProcessor processor = processorManager.getProcessor(cmd.getCmdCode());
         var processor = processorManager.getProcessor(cmd.CmdCode);
         processor.process(ctx, cmd, processorManager.DefaultExecutor);
     }
     //JAVA TO C# CONVERTER WARNING: 'final' catch parameters are not available in C#:
     //ORIGINAL LINE: catch (final Throwable t)
     catch (System.Exception t)
     {
         processException(ctx, msg, t);
     }
 }
Beispiel #17
0
 /// <summary>
 /// Runs the given RPC command on the client with the given <see cref="RpcCommand.TargetPeerID"/>
 /// as soon as possible and returns the result or throws an <see cref="RpcException"/>.
 /// </summary>
 public async Task <T> ExecuteOnClient <T>(RpcCommand command)
 {
     try {
         var clientID = command.TargetPeerID;
         if (clientID.Length == 0)
         {
             throw new Exception("No client ID given");
         }
         // Apply [RpcOptions(...)] from method declaration
         command.ApplyRpcOptionsFromCallStack();
         // Enqueue (and execute)
         clients.GetClient(clientID, commandBacklog).EnqueueCommand(command);
         // Wait for result until timeout
         return(await command.WaitForResult <T>());
     }
     catch (RpcException ex) {
         throw; // Rethrow RPC exception
     }
     catch (Exception ex) {
         throw new RpcException(new RpcFailure(RpcFailureType.Other, ex.Message)); // Wrap any other exception
     }
 }
Beispiel #18
0
        /// <summary>
        /// Sends the given command to the server now, reads the result or catches the
        /// exception, and sets the command's state accordingly.
        /// </summary>
        private async Task ExecuteOnServerNow(RpcCommand command)
        {
            RpcCommandResult result;
            var bodyJson = JsonLib.ToJson(command);

            try {
                var httpResponse = await httpPush.PostAsync(clientConfig.ServerUrl + "/push",
                                                            new StringContent(bodyJson, Encoding.UTF8, "application/json"));

                if (httpResponse.IsSuccessStatusCode)
                {
                    // Response (either success or remote failure) received.
                    result = JsonLib.FromJson <RpcCommandResult>(await httpResponse.Content.ReadAsStringAsync());
                }
                else
                {
                    // The server did not respond with 200 (which it should do even in case of
                    // a remote exception). So there is a communication error.
                    result = RpcCommandResult.FromFailure(command.ID,
                                                          new RpcFailure(RpcFailureType.RpcError, "Remote side problem with RPC call. HTTP status code " +
                                                                         (int)httpResponse.StatusCode));
                }
            }
            catch {
                // Could not reach server.
                result = RpcCommandResult.FromFailure(command.ID,
                                                      new RpcFailure(RpcFailureType.Timeout, "Could not reach the server"));
            }
            // When a result was received (i.e. when there was no network problem), the command is finished
            if (false == (result.Failure?.IsNetworkProblem == true) && command.ID == serverCache.CurrentCommand?.ID)
            {
                serverCache.FinishCurrentCommand();
            }
            // Finish command
            command.Finish(result);
        }
Beispiel #19
0
 /// <summary>
 /// Runs the given RPC command on the client as soon as possible
 /// and returns the result or throws an <see cref="RpcException"/>.
 /// See <see cref="RpcCommand.CreateForClient"/> for the parameters.
 /// </summary>
 protected Task <T> ExecuteOnClient <T>(string methodName, params object[] methodParameters) =>
 RpcServerEngine.Instance.ExecuteOnClient <T>(
     RpcCommand.CreateForClient(ClientID, methodName, methodParameters));
Beispiel #20
0
 private static void DefineCommand(string command, RpcCommand handler)
 {
     CommandHandlers[command] = handler;
 }
Beispiel #21
0
 /// <summary>
 /// Implement this method to map the encoded RPC commands to
 /// the real methods in this class. Thrown exceptions are catched
 /// and the calling peer gets notified about a
 /// <see cref="RpcFailureType.RemoteException"> failure.
 /// If successfull, returns a task with the JSON-encoded result or null
 /// if the method has no return type (void).
 /// If the given command name is undefined in this implementation, returns null
 /// (not a Task with value null, but null itself!).
 /// </summary>
 public abstract Task <string?>?Execute(RpcCommand command);
Beispiel #22
0
 // Mapping of RpcCommand to real method calls (boilerplate code; we could auto-generate this method later)
 public override Task <string?>?Execute(RpcCommand command) => command.MethodName switch
 {
     "SayHelloToClient" => SayHelloToClient(command.GetParam <Greeting>(0)).ToJson(),
Beispiel #23
0
 // Mapping of RpcCommand to real method calls (boilerplate code; we could auto-generate this method later)
 public override Task <string?>?Execute(RpcCommand command) => command.MethodName switch
 {
     "GetBalance" => GetBalance(command.GetParam <int>(0)).ToJson(),
Beispiel #24
0
 // Mapping of RpcCommand to real method calls (boilerplate code; we could auto-generate this method later)
 public override Task <string?>?Execute(RpcCommand command) => command.MethodName switch
 {
     "AddNumbers" => AddNumbers(command.GetParam <int>(0), command.GetParam <int>(1)).ToJson(),
Beispiel #25
0
 /// <summary>
 /// Runs the given RPC command on the server as soon as possible
 /// and returns the result or throws an <see cref="RpcException"/>.
 /// See <see cref="RpcCommand.CreateForServer"/> for the parameters.
 /// </summary>
 protected Task <T> ExecuteOnServer <T>(string methodName, params object[] methodParameters) =>
 RpcClientEngine.Instance.ExecuteOnServer <T>(RpcCommand.CreateForServer(methodName, methodParameters));
 /// <seealso cref= CommandEncoder#encode(io.netty.channel.IChannelHandlerContext, java.io.Serializable, io.netty.buffer.IByteBuffer) </seealso>
 //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
 //ORIGINAL LINE: @Override public void encode(io.netty.channel.IChannelHandlerContext ctx, java.io.Serializable msg, io.netty.buffer.IByteBuffer out) throws Exception
 public virtual void encode(IChannelHandlerContext ctx, object msg, IByteBuffer @out)
 {
     try
     {
         if (msg is RpcCommand)
         {
             /*
              * ver: version for protocol
              * type: request/response/request oneway
              * cmdcode: code for remoting command
              * ver2:version for remoting command
              * requestId: id of request
              * codec: code for codec
              * (req)timeout: request timeout.
              * (resp)respStatus: response status
              * classLen: length of request or response class name
              * headerLen: length of header
              * cotentLen: length of content
              * className
              * header
              * content
              */
             RpcCommand cmd = (RpcCommand)msg;
             @out.WriteByte(RpcProtocol.PROTOCOL_CODE);
             @out.WriteByte(cmd.Type);
             @out.WriteShort(((RpcCommand)msg).CmdCode.value());
             @out.WriteByte(cmd.Version);
             @out.WriteInt(cmd.Id);
             @out.WriteByte(cmd.Serializer);
             if (cmd is RequestCommand)
             {
                 //timeout
                 @out.WriteInt(((RequestCommand)cmd).Timeout);
             }
             if (cmd is ResponseCommand)
             {
                 //response status
                 ResponseCommand response = (ResponseCommand)cmd;
                 @out.WriteShort((short)response.ResponseStatus);
             }
             @out.WriteShort(cmd.ClazzLength);
             @out.WriteShort(cmd.HeaderLength);
             @out.WriteInt(cmd.ContentLength);
             if (cmd.ClazzLength > 0)
             {
                 @out.WriteBytes(cmd.Clazz);
             }
             if (cmd.HeaderLength > 0)
             {
                 @out.WriteBytes(cmd.Header);
             }
             if (cmd.ContentLength > 0)
             {
                 @out.WriteBytes(cmd.Content);
             }
         }
         else
         {
             string warnMsg = "msg type [" + msg.GetType() + "] is not subclass of RpcCommand";
             logger.LogWarning(warnMsg);
         }
     }
     catch (Exception e)
     {
         logger.LogError("Exception caught!", e);
         throw;
     }
 }
Beispiel #27
0
 public async Task Send(RpcCommand cmd)
 {
     await client.SendInstant(api.Serialize(cmd));
 }
 /// <seealso cref= CommandEncoder#encode(IChannelHandlerContext, Serializable, IByteBuffer) </seealso>
 //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
 //ORIGINAL LINE: @Override public void encode(io.netty.channel.IChannelHandlerContext ctx, java.io.Serializable msg, io.netty.buffer.IByteBuffer out) throws Exception
 public virtual void encode(IChannelHandlerContext ctx, object msg, IByteBuffer @out)
 {
     try
     {
         if (msg is RpcCommand)
         {
             /*
              * proto: magic code for protocol
              * ver: version for protocol
              * type: request/response/request oneway
              * cmdcode: code for remoting command
              * ver2:version for remoting command
              * requestId: id of request
              * codec: code for codec
              * switch: function switch
              * (req)timeout: request timeout.
              * (resp)respStatus: response status
              * classLen: length of request or response class name
              * headerLen: length of header
              * cotentLen: length of content
              * className
              * header
              * content
              * crc (optional)
              */
             int        index = @out.WriterIndex;
             RpcCommand cmd   = (RpcCommand)msg;
             @out.WriteByte(RpcProtocolV2.PROTOCOL_CODE);
             var  version = ctx.Channel.GetAttribute(Connection.VERSION);
             byte ver     = RpcProtocolV2.PROTOCOL_VERSION_1;
             if (version != null && version.Get() != null)
             {
                 ver = (byte)version.Get();
             }
             @out.WriteByte(ver);
             @out.WriteByte(cmd.Type);
             @out.WriteShort(((RpcCommand)msg).CmdCode.value());
             @out.WriteByte(cmd.Version);
             @out.WriteInt(cmd.Id);
             @out.WriteByte(cmd.Serializer);
             @out.WriteByte(cmd.ProtocolSwitch.toByte());
             if (cmd is RequestCommand)
             {
                 //timeout
                 @out.WriteInt(((RequestCommand)cmd).Timeout);
             }
             if (cmd is ResponseCommand)
             {
                 //response status
                 ResponseCommand response = (ResponseCommand)cmd;
                 @out.WriteShort((short)response.ResponseStatus);
             }
             @out.WriteShort(cmd.ClazzLength);
             @out.WriteShort(cmd.HeaderLength);
             @out.WriteInt(cmd.ContentLength);
             if (cmd.ClazzLength > 0)
             {
                 @out.WriteBytes(cmd.Clazz);
             }
             if (cmd.HeaderLength > 0)
             {
                 @out.WriteBytes(cmd.Header);
             }
             if (cmd.ContentLength > 0)
             {
                 @out.WriteBytes(cmd.Content);
             }
             if (ver == RpcProtocolV2.PROTOCOL_VERSION_2 && cmd.ProtocolSwitch.isOn(ProtocolSwitch.CRC_SWITCH_INDEX))
             {
                 // compute the crc32 and write to out
                 byte[] frame = new byte[@out.ReadableBytes];
                 @out.GetBytes(index, frame);
                 @out.WriteInt(CrcUtil.crc32(frame));
             }
         }
         else
         {
             string warnMsg = "msg type [" + msg.GetType() + "] is not subclass of RpcCommand";
             logger.LogWarning(warnMsg);
         }
     }
     catch (Exception e)
     {
         logger.LogError("Exception caught!", e);
         throw;
     }
 }