/// <summary> /// Invokes a method remotely, and returns the result /// </summary> /// <returns>The result of the remote invocation.</returns> /// <param name="handle">The remote instance handle, or zero for null.</param> /// <param name="method">The method to invoke remotely.</param> /// <param name="arguments">The values given to the method when invoked.</param> /// <param name="isWrite">If set to <c>true</c> this is a write field or property request.</param> public Task <object> InvokeRemoteMethodAsync(long handle, System.Reflection.MemberInfo method, object[] arguments, bool isWrite) { var methodstring = m_typeSerializer.GetShortDefinition(method); var type = m_typeSerializer.GetShortTypeName(method.DeclaringType); Type[] methodtypes; if (method is System.Reflection.MethodInfo) { var mi = method as System.Reflection.MethodInfo; methodtypes = mi.GetParameters().Select(x => x.ParameterType).ToArray(); } else if (method is System.Reflection.ConstructorInfo) { var ci = method as System.Reflection.ConstructorInfo; methodtypes = ci.GetParameters().Select(x => x.ParameterType).ToArray(); } else if (method is System.Reflection.FieldInfo) { if (isWrite) { methodtypes = new Type[] { ((System.Reflection.FieldInfo)method).FieldType } } ; else { methodtypes = new Type[0]; } } else if (method is System.Reflection.PropertyInfo) { var pi = method as System.Reflection.PropertyInfo; var indexTypes = pi.GetIndexParameters().Select(x => x.ParameterType); if (isWrite) { indexTypes = new Type[] { pi.PropertyType } }
private static async Task ListenForRequests(RPCPeer peer, string prefix, string path) { Program.DebugConsoleOutput($"Setting up listener ..."); var tp = new TypeSerializer(false, false); var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.IP); socket.Connect(new SockRock.UnixEndPoint(prefix + path + "_fd")); Program.DebugConsoleOutput($"Connected to fd socket, reading initial data"); SpawnedServer server; // Start by reading and verifying the protocol intial data var buffer = new byte[1024]; var count = socket.Receive(buffer); Program.DebugConsoleOutput($"Got protocol data with {count} bytes"); using (var ms = new System.IO.MemoryStream(buffer, 0, count, false)) using (var bcs = new BinaryConverterStream(ms, tp, false)) { var desc = await bcs.ReadAnyAsync <InitialProtocolDescription>(); if (desc.Version != 1) { throw new Exception($"Expected protocol version 1, but got {desc.Version}"); } if (desc.RequestSignature != tp.GetShortTypeName(typeof(SocketRequest))) { throw new Exception($"Expected type name to be {tp.GetShortTypeName(typeof(SocketRequest))}, but it was {desc.RequestSignature}"); } if (!peer.RemoteHandler.TryGetLocalObject(desc.ServerHandle, out var obj) || obj == null) { throw new Exception($"Unable to find the instance with the given handle: {desc.ServerHandle}"); } server = obj as SpawnedServer; if (server == null) { throw new Exception($"Unable to find the instance with the given handle: {desc.ServerHandle}, got something that is not a server ..."); } } Program.DebugConsoleOutput($"Protocol verification completed, starting main loop"); // Prepare the handle var rchandle = socket.Handle.ToInt32(); try { // Use a single allocated buffer for all requests using (var ms = new System.IO.MemoryStream()) using (var bcs = new BinaryConverterStream(ms, tp, false)) { Program.DebugConsoleOutput("{0} Entering main loop", System.Diagnostics.Process.GetCurrentProcess().Id); while (socket.Connected) { try { // Get the next request from the socket Program.DebugConsoleOutput("{0} Getting file handle", System.Diagnostics.Process.GetCurrentProcess().Id); var req = SockRock.ScmRightsImplementation.recv_fds(rchandle); if (req == null) { Program.DebugConsoleOutput("{0} Socket closed", System.Diagnostics.Process.GetCurrentProcess().Id); break; } Program.DebugConsoleOutput("{0} Got request, parsing ...", System.Diagnostics.Process.GetCurrentProcess().Id); // Copy the buffer into the stream we read from ms.Position = 0; ms.Write(req.Item2, 0, req.Item2.Length); ms.Position = 0; // Extract the data var data = await bcs.ReadAnyAsync <SocketRequest>(); Program.DebugConsoleOutput("{0}, Decoded request, local handle is {1} remote handle is {2}", System.Diagnostics.Process.GetCurrentProcess().Id, req.Item1[0], data.Handle); // All set, fire the request Task.Run( () => server.HandleRequestSimple(req.Item1[0], new IPEndPoint(IPAddress.Parse(data.RemoteIP), data.RemotePort), data.LogTaskID) ).ContinueWith( _ => Program.DebugConsoleOutput("{0}: Request handling completed", System.Diagnostics.Process.GetCurrentProcess().Id) ); } catch (Exception ex) { Program.ConsoleOutput("{0}: Processing failed: {1}", System.Diagnostics.Process.GetCurrentProcess().Id, ex); return; } } } } finally { var st = DateTime.Now; Program.DebugConsoleOutput("{0}: Stopping spawned process", System.Diagnostics.Process.GetCurrentProcess().Id); server.Stop(TimeSpan.FromMinutes(5)); Program.DebugConsoleOutput("{0}: Stopped spawned process in {1}", System.Diagnostics.Process.GetCurrentProcess().Id, DateTime.Now - st); peer.Dispose(); Program.DebugConsoleOutput("{0}: Stopped peer in {1}", System.Diagnostics.Process.GetCurrentProcess().Id, DateTime.Now - st); } }