using System; using System.Diagnostics; using System.Globalization; using System.IO; using System.Net.WebSockets; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace WebDesktopUpdater { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddSingleton(Configuration); services.AddControllers(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } //app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); app.UseWebSockets(new WebSocketOptions { KeepAliveInterval = TimeSpan.FromSeconds(10) }); app.Use(async (context, next) => { if (context.Request.Path == "/") { if (context.WebSockets.IsWebSocketRequest) { WebSocket socket = await context.WebSockets.AcceptWebSocketAsync(); byte[] buffer = new byte[1024 * 4]; WebSocketReceiveResult result = await socket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None); while (!result.CloseStatus.HasValue) { string msg = Read(buffer, result); if (msg.Equals("Ping")) { await Write(DateTime.UtcNow.ToString(CultureInfo.InvariantCulture), socket, result); } if (msg.Equals("Start")) { Process updater = Update(); var handler = new DataReceivedEventHandler(async (sender, e) => { await Write(e.Data, socket, result); }); updater.OutputDataReceived += handler; updater.ErrorDataReceived += handler; updater.Start(); updater.BeginOutputReadLine(); updater.BeginErrorReadLine(); } result = await socket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None); } await socket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None); } else { byte[] html = Encoding.UTF8.GetBytes(await File.ReadAllTextAsync(Environment.CurrentDirectory + "/updater.html")); await context.Response.Body.WriteAsync(html, 0, html.Length); } } }); } private Process Update() { FileInfo file = new FileInfo(Configuration.GetValue("UpdaterScript")); if (file.DirectoryName == null) throw new FileNotFoundException(file.FullName); Process process = new Process(); ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.WindowStyle = ProcessWindowStyle.Hidden; startInfo.FileName = "/bin/bash"; startInfo.WorkingDirectory = file.DirectoryName; startInfo.Arguments = "./" + file.Name; startInfo.RedirectStandardError = true; startInfo.RedirectStandardOutput = true; startInfo.UseShellExecute = false; process.StartInfo = startInfo; return process; } private string Read(in byte[] buffer, in WebSocketReceiveResult result) { return Encoding.UTF8.GetString(new ArraySegment(buffer, 0, result.Count)); } private async Task Write(string message, WebSocket socket, WebSocketReceiveResult result) { try { await socket.SendAsync(new ArraySegment(Encoding.UTF8.GetBytes(message)), result.MessageType, result.EndOfMessage, CancellationToken.None); } catch (Exception) {} } } }