/// <summary> /// Initializes a new instance of the <see cref="T:Ceen.Httpd.Cli.UnixSpawn.SpawnedServer"/> class. /// </summary> /// <param name="usessl">If set to <c>true</c> usessl.</param> /// <param name="configfile">Configfile.</param> /// <param name="storage">Storage.</param> public SpawnedServer(bool usessl, string configfile, IStorageCreator storage) { var config = ConfigParser.ValidateConfig(ConfigParser.ParseTextFile(configfile)); config.Storage = storage ?? new MemoryStorageCreator(); try { m_pollhandler = new SockRock.KqueueHandler(); } catch (Exception e1) { try { m_pollhandler = new SockRock.EpollHandler(); } catch (Exception e2) { throw new PlatformNotSupportedException("Unable to create kqueue or epoll instance", new AggregateException(e1, e2)); } } m_pollhandler.WaitForShutdownAsync.ContinueWith(x => { Program.ConsoleOutput("The poll handler crashed, stopping this instance"); this.Stop(TimeSpan.FromSeconds(-5)); }, TaskContinuationOptions.NotOnRanToCompletion); base.Setup(usessl, config); }
/// <summary> /// Creates a new indirect runner /// </summary> /// <param name="path">The path to the config file.</param> /// <param name="useSSL">If set to <c>true</c> use ssl.</param> /// <param name="storage">The storage interface to use.</param> /// <param name="token">A cancellation token to use.</param> public IndirectRunner(string path, bool useSSL, IStorageCreator storage, CancellationToken token) { m_path = path; m_useSSL = useSSL; m_storage = storage; m_token = token; m_task = MonitorForRestartAsync(); }
/// <summary> /// Creates a new indirect runner /// </summary> /// <param name="path">The path to the config file.</param> /// <param name="useSSL">If set to <c>true</c> use ssl.</param> /// <param name="storage">The storage interface to use.</param> /// <param name="token">A cancellation token to use.</param> public IndirectRunner(string path, bool useSSL, IStorageCreator storage, CancellationToken token) { m_path = path; m_useSSL = useSSL; m_storage = storage; m_token = token; // Make sure we have an instance before continuing Instance = new SpawnRemoteInstance(m_path, m_useSSL, m_storage, m_token); m_task = MonitorForRestartAsync(); }
/// <summary> /// Initializes a new instance of the <see cref="T:Ceen.Httpd.Cli.Runner.InProcessRunner"/> class. /// </summary> /// <param name="usessl">If set to <c>true</c> use ssl.</param> /// <param name="configfile">The config file.</param> /// <param name="storage">The storage to use</param> /// <param name="token">The cancellation token to use</param> public InProcessWrapper(bool usessl, string configfile, IStorageCreator storage, CancellationToken token) { var config = ConfigParser.ValidateConfig(ConfigParser.ParseTextFile(configfile)); config.Storage = storage ?? new MemoryStorageCreator(); base.Setup(usessl, config); if (token.CanBeCanceled) { token.Register(() => this.Stop()); } }
/// <summary> /// Initializes a new instance of the <see cref="T:Ceen.Httpd.Cli.UnixSpawn.SpawnedServer"/> class. /// </summary> /// <param name="usessl">If set to <c>true</c> usessl.</param> /// <param name="configfile">Configfile.</param> /// <param name="storage">Storage.</param> public SpawnedServer(bool usessl, string configfile, IStorageCreator storage) { //// Mono version //var safeSocketHandleType = Type.GetType("System.Net.Sockets.SafeSocketHandle"); //var safeSocketHandleConstructor = safeSocketHandleType?.GetConstructor(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic, null, new Type[] { typeof(IntPtr), typeof(bool) }, null); //var socketConstructorSafeSocketHandle = safeSocketHandleType == null ? null : typeof(System.Net.Sockets.Socket).GetConstructor(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic, null, new Type[] { typeof(AddressFamily), typeof(SocketType), typeof(ProtocolType), safeSocketHandleType }, null); //// .Net Core version //var safeCloseSocketType = Type.GetType("System.Net.Sockets.SafeCloseSocket"); //var safeCloseSocketConstructor = safeCloseSocketType?.GetMethod("CreateSocket", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static, null, new Type[] { typeof(IntPtr) }, null); //var socketConstructorSafeCloseSocket = safeCloseSocketType == null ? null : typeof(System.Net.Sockets.Socket).GetConstructor(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic, null, new Type[] { safeCloseSocketType }, null); //if (safeSocketHandleConstructor != null && socketConstructorSafeSocketHandle != null) // m_createSocket = (handle) => (Socket)Activator.CreateInstance(typeof(Socket), AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp, Activator.CreateInstance(safeSocketHandleType, new IntPtr(handle), false)); //else if (safeCloseSocketConstructor != null && socketConstructorSafeCloseSocket != null) // m_createSocket = (handle) => (Socket)Activator.CreateInstance(typeof(Socket), safeCloseSocketConstructor.Invoke(null, new object[] { new IntPtr(handle) })); //else //throw new Exception("Unable to find a method to create sockets from handles ...."); var config = ConfigParser.ValidateConfig(ConfigParser.ParseTextFile(configfile)); config.Storage = storage ?? new MemoryStorageCreator(); try { m_pollhandler = new SockRock.KqueueHandler(); } catch (Exception e1) { try { m_pollhandler = new SockRock.EpollHandler(); } catch (Exception e2) { throw new PlatformNotSupportedException("Unable to create kqueue or epoll instance", new AggregateException(e1, e2)); } } base.Setup(usessl, config); }
/// <summary> /// Setup this instance /// </summary> /// <param name="usessl">If set to <c>true</c> usessl.</param> /// <param name="path">Path to the configuration file.</param> /// <param name="storage">The storage instance or null.</param> public void SetupFromFile(bool usessl, string path, IStorageCreator storage) { var config = ConfigParser.ValidateConfig(ConfigParser.ParseTextFile(path)); if (storage != null) { // Inject a wrapper to support async via callbacks if (System.AppDomain.CurrentDomain.IsDefaultAppDomain()) { config.Storage = storage; } else { config.Storage = new StorageCreatorAccessor(storage); } } else { config.Storage = new MemoryStorageCreator(); } base.Setup(usessl, config); }
protected override IWrappedRunner CreateRunner(string path, bool useSSL, IStorageCreator storage, CancellationToken token) { return(new InProcessWrapper(useSSL, path, storage, token)); }
/// <summary> /// Setup this instance /// </summary> /// <param name="usessl">If set to <c>true</c> usessl.</param> /// <param name="configfile">Path to the configuration file</param> /// <param name="storage">The storage instance or null</param> public void SetupFromFile(bool usessl, string configfile, IStorageCreator storage) { m_setupFromFile.Invoke(m_wrapped, new object[] { usessl, configfile, storage }); }
/// <summary> /// Initializes a new instance of the <see cref="T:Ceen.Httpd.HttpContext"/> class. /// </summary> /// <param name="request">The HTTP request.</param> /// <param name="response">The HTTP response.</param> /// <param name="storage">The storage instance</param> public HttpContext(HttpRequest request, HttpResponse response, IStorageCreator storage) { this.Request = request; this.Response = response; this.Storage = storage; }
/// <summary> /// Creates a new runner instance /// </summary> /// <returns>The runner instance.</returns> /// <param name="path">The path to the config file.</param> /// <param name="useSSL">If set to <c>true</c> use ssl.</param> /// <param name="storage">The storage interface to use.</param> /// <param name="token">A cancellation token to use.</param> protected override IWrappedRunner CreateRunner(string path, bool useSSL, IStorageCreator storage, CancellationToken token) { return(new SpawnRemoteInstance(path, useSSL, storage, token)); }
/// <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(); } }
protected abstract IWrappedRunner CreateRunner(string path, bool useSSL, IStorageCreator storage, System.Threading.CancellationToken token);
public void AddStorage(IStorageCreator storage) { this.storage = storage; }