diff --git a/GeneratorServer.sln b/GeneratorServer.sln new file mode 100644 index 0000000..872b78c --- /dev/null +++ b/GeneratorServer.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.35027.167 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeneratorServer", "GeneratorServer\GeneratorServer.csproj", "{3CD16E16-87B1-4B3A-A482-06BC2FF38406}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HTTP", "HTTP\HTTP.csproj", "{BA36BD06-3E6F-4C71-8FBB-3F17AD60A7B1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PNG", "PNG\PNG.csproj", "{30C7F87B-1C7C-49E9-8563-4D845D204CC0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3CD16E16-87B1-4B3A-A482-06BC2FF38406}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3CD16E16-87B1-4B3A-A482-06BC2FF38406}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3CD16E16-87B1-4B3A-A482-06BC2FF38406}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3CD16E16-87B1-4B3A-A482-06BC2FF38406}.Release|Any CPU.Build.0 = Release|Any CPU + {BA36BD06-3E6F-4C71-8FBB-3F17AD60A7B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BA36BD06-3E6F-4C71-8FBB-3F17AD60A7B1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BA36BD06-3E6F-4C71-8FBB-3F17AD60A7B1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BA36BD06-3E6F-4C71-8FBB-3F17AD60A7B1}.Release|Any CPU.Build.0 = Release|Any CPU + {30C7F87B-1C7C-49E9-8563-4D845D204CC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {30C7F87B-1C7C-49E9-8563-4D845D204CC0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {30C7F87B-1C7C-49E9-8563-4D845D204CC0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {30C7F87B-1C7C-49E9-8563-4D845D204CC0}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {5755C00D-E811-4169-9B74-4EEE07099BE6} + EndGlobalSection +EndGlobal diff --git a/GeneratorServer/GeneratorServer.csproj b/GeneratorServer/GeneratorServer.csproj new file mode 100644 index 0000000..6e9e24e --- /dev/null +++ b/GeneratorServer/GeneratorServer.csproj @@ -0,0 +1,29 @@ + + + net8.0 + disable + enable + + + + Exe + + + + none + true + + + + + + + + + + + + + + + diff --git a/GeneratorServer/Program.cs b/GeneratorServer/Program.cs new file mode 100644 index 0000000..f9a4746 --- /dev/null +++ b/GeneratorServer/Program.cs @@ -0,0 +1,89 @@ +using System.Security.Cryptography.X509Certificates; +using Uwaa.HTTP; +using Uwaa.HTTP.Routing; +using Uwaa.PNG; + +namespace GeneratorServer; + +internal class Program +{ + static void Main(string[] args) + { + Console.WriteLine("Creating router"); + Router router = CreateRouter(); + + Console.WriteLine("Starting HTTP"); + HttpServer http = new HttpServer(80, null, router); + http.Start(); + + if (!File.Exists("certs/certificate.crt") || !File.Exists("certs/private.key")) + { + #if RELEASE + Console.WriteLine("Warning: No HTTPS, \"certificate.crt\" and/or \"private.key\" are missing in \"certs\" directory."); + #endif + } + else + { + Console.WriteLine("Starting HTTPS"); + HttpServer https = new HttpServer(443, X509Certificate2.CreateFromPemFile("certs/certificate.crt", "certs/private.key"), router); + https.Start(); + } + + Console.WriteLine("Ready"); + Task.Delay(-1).Wait(); + } + + static Router CreateRouter() + { + var router = new Router(); + router.Add("background", new BGGenerator()); + router.Add(new StaticEndpoint(HttpResponse.NotFound())); + return router; + } +} + +class BGGenerator : RouterBase +{ + public override HttpMethod Method => HttpMethod.GET; + + public override int Arguments => 0; + + protected override Task GetResponseInner(HttpRequest req, HttpClientInfo info, ArraySegment path) + { + MIMEType contentType = new MIMEType("image", "png"); + if (!req.CanAccept(contentType)) + return Task.FromResult(HttpResponse.NotAcceptable())!; + + const int width = 100; + const int height = 100; + PngBuilder png = PngBuilder.Create(width, height, false); + + Pixel left = new Pixel((byte)Random.Shared.Next(0, 256), (byte)Random.Shared.Next(0, 256), (byte)Random.Shared.Next(0, 256)); + Pixel right = new Pixel((byte)Random.Shared.Next(0, 256), (byte)Random.Shared.Next(0, 256), (byte)Random.Shared.Next(0, 256)); + Pixel top = new Pixel((byte)Random.Shared.Next(0, 256), (byte)Random.Shared.Next(0, 256), (byte)Random.Shared.Next(0, 256)); + Pixel bottom = new Pixel((byte)Random.Shared.Next(0, 256), (byte)Random.Shared.Next(0, 256), (byte)Random.Shared.Next(0, 256)); + for (int y = 0; y < height; y++) + for (int x = 0; x < width; x++) + { + Pixel px = Lerp(Lerp(left, right, (float)x / width), Lerp(top, bottom, (float)y / height), 0.5f); + png.SetPixel(px, x, y); + } + + return Task.FromResult(HttpResponse.OK(new HttpContent(contentType, png.Save())))!; + } + + static Pixel Lerp(Pixel min, Pixel max, float factor) + { + return new Pixel(Lerp(min.R, max.R, factor), Lerp(min.G, max.G, factor), Lerp(min.B, max.B, factor)); + } + + static byte Lerp(byte min, byte max, float factor) + { + return (byte)(min + (max - min) * factor); + } + + static float Lerp(float min, float max, float factor) + { + return min + (max - min) * factor; + } +} \ No newline at end of file diff --git a/GeneratorServer/README.md b/GeneratorServer/README.md new file mode 100644 index 0000000..0bc291b --- /dev/null +++ b/GeneratorServer/README.md @@ -0,0 +1 @@ +HTTP server which generates images on request \ No newline at end of file