public void RemoteReferences() { using (var setup = new ClientServerTester(FailMethod, FailMethod)) { var client = new RPCPeer(setup.Client); var server = new RPCPeer(setup.Server, typeof(RemoteInvokeAble)); // Let the client create proxy objects client.AddProxyGenerator((peer, type, handle) => new RemoteInvokeAbleProxy(peer, handle)); // Let the server pass the object by reference server.TypeSerializer.RegisterSerializationAction(typeof(RemoteInvokeAble), SerializationAction.Reference); // Run the tests using (var proxy = client.InvokeRemoteMethodAsync <IRemoteInvokeAbleProxy>(0, typeof(RemoteInvokeAble).GetConstructor(new Type[0]), null, false).Result) { if (proxy.Echo("test message") != "Echo : test message") { throw new Exception("Expected echo message back"); } if (proxy.ID != 42) { throw new Exception("Expected 42 as the ID"); } proxy.ID = 45; if (proxy.ID != 45) { throw new Exception("Expected 45 as the ID"); } if (proxy.CreateTime == 0) { throw new Exception("Expected a proxy creation time"); } proxy.CreateTime = 0; if (proxy.CreateTime != 0) { throw new Exception("Expected no proxy creation time"); } } } }
private void HandleNewAddress(RPCPeer address, StateOfNeoContext db) { var newNode = default(Node); string successUrl = null; var ports = this.netSettings.GetPorts(); foreach (var portWithType in ports) { var url = portWithType.GetFullUrl(address.Address.ToMatchedIp()); try { var rpcResult = RpcCaller.MakeRPCCall <RPCResponseBody <int> >(url, "getblockcount") .GetAwaiter() .GetResult(); if (rpcResult?.Result > 0) { successUrl = url; newNode = this.CreateNodeOfAddress(address.Address, portWithType.Type, successUrl, NodeAddressType.RPC); break; } } catch (Exception e) { Log.Error($"Get blockcount parse error {e.Message}", e); break; } } if (newNode == default(Node)) { var httpTypes = new string[] { "https", "http" }; foreach (var httpType in httpTypes) { var url = $"{httpType}://{address.Address.ToMatchedIp()}"; var heightResponse = HttpRequester.MakeRestCall <HeightResponseObject>($@"{url}/api/main_net/v1/get_height", HttpMethod.Get) .GetAwaiter() .GetResult(); if (heightResponse != null) { successUrl = url; newNode = this.CreateNodeOfAddress(address.Address, httpType, successUrl, NodeAddressType.REST, NodeCallsConstants.NeoScan); break; } var versionResponse = HttpRequester.MakeRestCall <NeoNotificationVersionResponse>($@"{url}/v1/version", HttpMethod.Get) .GetAwaiter() .GetResult(); if (versionResponse != null) { successUrl = url; newNode = this.CreateNodeOfAddress(address.Address, httpType, successUrl, NodeAddressType.REST, NodeCallsConstants.NeoNotification); break; } } } if (newNode != null) { var newNodeAddress = new NodeAddress { Ip = address.Address.ToMatchedIp(), Node = newNode }; var peer = db.Peers.FirstOrDefault(x => x.Ip == address.Address.ToMatchedIp()); var result = LocationCaller.UpdateNode(newNode, newNodeAddress.Ip).GetAwaiter().GetResult(); newNode.NodeAddresses.Add(newNodeAddress); db.NodeAddresses.Add(newNodeAddress); db.Nodes.Add(newNode); peer.Node = newNode; db.SaveChanges(); } }
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); } }
public void AddPeer(RPCPeer peer) { this.PeersCollected.Add(peer); }
/// <summary> /// Initializes a new instance of the <see cref="T:Ceen.Httpd.Cli.SubProcess.SpawnRemoteInstance"/> class. /// </summary> /// <param name="path">The path to the config file</param> /// <param name="usessl">If set to <c>true</c> use ssl.</param> public SpawnRemoteInstance(string path, bool usessl, IStorageCreator storage, CancellationToken token) { m_path = path; m_useSSL = usessl; m_storage = storage; var prefix = m_hiddenSocketPath ? "\0" : string.Empty; var sockid = string.Format("ceen-socket-{0}", new Random().Next().ToString("x8")); if (m_hiddenSocketPath) { m_socketpath = sockid; } else { var pathPrefix = Environment.GetEnvironmentVariable("CEEN_SOCKET_FOLDER"); if (string.IsNullOrWhiteSpace(pathPrefix)) { pathPrefix = System.IO.Path.GetTempPath(); } m_socketpath = System.IO.Path.GetFullPath(System.IO.Path.Combine(pathPrefix, sockid)); } // Setup a socket server, start the child, and stop the server using ((SystemHelper.IsCurrentOSPosix && !m_hiddenSocketPath) ? new DeleteFilesHelper(m_socketpath, m_socketpath + "_fd") : null) using (var serveripcsocket = SystemHelper.IsCurrentOSPosix ? new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.IP) : null) using (var serverfdsocket = SystemHelper.IsCurrentOSPosix ? new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.IP) : null) { if (SystemHelper.IsCurrentOSPosix) { serveripcsocket.Bind(new SockRock.UnixEndPoint(prefix + m_socketpath)); serveripcsocket.Listen(1); serverfdsocket.Bind(new SockRock.UnixEndPoint(prefix + m_socketpath + "_fd")); serverfdsocket.Listen(1); } // Launch the child process m_proc = StartRemoteProcess(); // TODO: Consider some multiplexer to allow multiple outputs without mixing the contents var tasks = Task.WhenAll( m_proc.StandardOutput.BaseStream.CopyToAsync(Console.OpenStandardOutput()), m_proc.StandardError.BaseStream.CopyToAsync(Console.OpenStandardError()), Console.OpenStandardInput().CopyToAsync(m_proc.StandardInput.BaseStream) ); if (SystemHelper.IsCurrentOSPosix) { var ct = new CancellationTokenSource(); // Prepare cancellation after 5 seconds Task.Delay(5000, ct.Token).ContinueWith(_ => { serveripcsocket.Dispose(); serverfdsocket.Dispose(); }); // Get the first connection m_ipcSocket = serveripcsocket.Accept(); m_fdSocket = serverfdsocket.Accept(); // Stop the timer ct.Cancel(); } //and then don't listen anymore } var ipc = new InterProcessConnection(new NetworkStream(m_ipcSocket, true)); m_peer = new RPCPeer( ipc, typeof(IStorageEntry), typeof(IStorageCreator) ); // We pass these by reference m_peer.TypeSerializer.RegisterSerializationAction(typeof(IStorageEntry), SerializationAction.Reference); m_peer.TypeSerializer.RegisterSerializationAction(typeof(IStorageCreator), SerializationAction.Reference); // Set up special handling for serializing an endpoint instance m_peer.TypeSerializer.RegisterEndPointSerializers(); m_peer.TypeSerializer.RegisterIPEndPointSerializers(); m_main = Task.Run(async() => { try { using (m_fdSocket) using (m_ipcSocket) await ipc.RunMainLoopAsync(false); } finally { Program.DebugConsoleOutput("{0}: Finished main loop, no longer connected to: {1}", System.Diagnostics.Process.GetCurrentProcess().Id, m_proc.Id); m_proc.WaitForExit((int)TimeSpan.FromMinutes(1).TotalMilliseconds); if (!m_proc.HasExited) { m_proc.Kill(); } Program.DebugConsoleOutput("{0}: Target now stopped: {1}", System.Diagnostics.Process.GetCurrentProcess().Id, m_proc.Id); } }); if (token.CanBeCanceled) { token.Register(() => this.Stop()); } // Register the storage item, since it is a different concrete class (i.e. not the interface) if (storage != null) { m_peer.TypeSerializer.RegisterSerializationAction(storage.GetType(), SerializationAction.Reference); m_peer.RegisterLocalObjectOnRemote(storage, typeof(IStorageCreator)).Wait(); } m_peer.AddAutomaticProxy(typeof(SpawnedServer), typeof(ISpawnedServerProxy)); m_proxy = m_peer.CreateAsync <ISpawnedServerProxy>(typeof(SpawnedServer), usessl, path, storage).Result; if (SystemHelper.IsCurrentOSPosix) { // Prepare the file descriptor socket m_fdSocketTypeSerializer = new TypeSerializer(false, false); SetupDescriptorSocket().Wait(); } }
public RemoteIntProxy(RPCPeer peer, long handle) : base(peer, typeof(RemoteInt), handle) { }
public void RemoteInvoke() { using (var setup = new ClientServerTester(FailMethod, FailMethod)) { var client = new RPCPeer(setup.Client); var server = new RPCPeer(setup.Server, new Type[] { typeof(System.IO.Directory) }, (m, a) => m.Name == nameof(System.IO.Directory.GetCurrentDirectory)); var result = client.InvokeRemoteMethodAsync <string>(0L, typeof(System.IO.Directory).GetMethod(nameof(System.IO.Directory.GetCurrentDirectory)), null, false).Result; if (result != System.IO.Directory.GetCurrentDirectory()) { throw new Exception("Failed to get the correct "); } Exception res = null; // Try unsupported type: try { client.InvokeRemoteMethodAsync(0, typeof(System.IO.File).GetMethod(nameof(System.IO.File.Create)), new object[] { "test.txt" }, false).Wait(); } catch (Exception ex) { res = ex; } if (res == null) { throw new Exception("Unwanted access to other type"); } // Try other method res = null; try { client.InvokeRemoteMethodAsync(0, typeof(System.IO.Directory).GetMethod(nameof(System.IO.Directory.CreateDirectory)), new object[] { "testdir" }, false).Wait(); } catch (Exception ex) { res = ex; } if (res == null) { throw new Exception("Unwanted access to other method"); } // Try invoking on the client res = null; try { server.InvokeRemoteMethodAsync <string>(0, typeof(System.IO.Directory).GetMethod(nameof(System.IO.Directory.GetCurrentDirectory)), null, false).Wait(); } catch (Exception ex) { res = ex; } if (res == null) { throw new Exception("Unwanted access to client method"); } } }
public RemoteInvokeAbleProxy(RPCPeer peer, long handle) : base(peer, typeof(RemoteInvokeAble), handle) { }