Example #1
0
        void OnContext(IAsyncResult ar)
        {
            try {
                var ctx  = listener.EndGetContext(ar);
                var path = ctx.Request.Url.LocalPath;

                System.Console.WriteLine("{0} {1}", ctx.Request.HttpMethod, path);

                if (ctx.Request.HttpMethod == "GET")
                {
                    if (path == "/work")
                    {
                        var idx = rand.Next() % work.Count;
                        var w   = work[idx];
                        if (w.Finished || w.HandedOut)
                        {
                            w = (from ww in work where !ww.Finished && !ww.HandedOut select ww).FirstOrDefault();
                        }

                        if (w != null)
                        {
                            w.Finished               = false;
                            w.HandedOut              = true;
                            ctx.Response.StatusCode  = 200;
                            ctx.Response.ContentType = "text/xml";
                            w.Save(ctx.Response.OutputStream);
                            ctx.Response.Close();
                        }
                        else
                        {
                            ctx.Response.StatusCode = 404;
                            ctx.Response.Close();
                        }
                    }
                    else if (path == "/img" || path == "/favicon.ico")
                    {
                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "image/png";
                        finalBuffer.SavePng(ctx.Response.OutputStream);
                        ctx.Response.Close();
                    }
                    else if (path == "/")
                    {
                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "text/html";
                        using (var w = new StreamWriter(ctx.Response.OutputStream, Encoding.UTF8)) {
                            w.WriteLine("<!DOCTYPE html>");
                            w.WriteLine("<html><head><title>Frank's Distributed Raytracer</title>");
                            w.WriteLine("</head><body style='font-family:sans-serif;'>");
                            w.WriteLine("<h1>Frank's Distributed Raytracer</h1>");
                            w.WriteLine("<img src='/img' style='max-width:640px'>");
                            w.WriteLine("<h2>Progress</h2>");
                            var numFini = (from ww in work where ww.Finished select ww).Count();
                            var p       = (numFini * 100) / work.Count;
                            w.WriteLine("<p><strong>{0} of {1}</strong> blocks complete ({2}%)</p>", numFini, work.Count, p);
                            var mins = 0.0;
                            var pps  = 0.0;
                            var t    = DateTime.UtcNow;
                            if (firstBlockTime.HasValue)
                            {
                                var dt = t - firstBlockTime.Value;
                                pps = (numFini - 1) * work[0].Width * work[0].Height / dt.TotalSeconds;
                                var tt = (dt.TotalMinutes * 100) / p;
                                mins = tt - dt.TotalMinutes;
                            }
                            w.WriteLine("<p><strong>{0}</strong> mins remaining ({1})</p>", (int)(mins + 0.5), DateTime.Now.AddMinutes(mins));
                            w.WriteLine("<p><strong>{0}</strong> pixels / sec</p>", (int)pps);
                            w.WriteLine("<h2>Scene</h2>");
                            w.WriteLine("<code><pre>");
                            w.WriteLine(HtmlEscape(scene.SaveXml()));
                            w.WriteLine("</pre></code>");
                            w.WriteLine("</body></html>");
                        }
                        ctx.Response.Close();
                    }
                    else
                    {
                        ctx.Response.StatusCode = 404;
                        ctx.Response.Close();
                    }
                }
                else
                {
                    if (path.StartsWith("/work/") && path.EndsWith("/pixels"))
                    {
                        var wid = int.Parse(path.Split('/')[2]);
                        var w   = work[wid];
                        var pb  = PixelBuffer.OpenBinary(ctx.Request.InputStream);
                        finalBuffer.SetPixels(w.X, w.Y, pb);
                        w.Finished = true;
                        if (!firstBlockTime.HasValue)
                        {
                            firstBlockTime = DateTime.UtcNow;
                        }
                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "text/plain";
                        ctx.Response.Close();
                    }
                    else
                    {
                        ctx.Response.StatusCode = 404;
                        ctx.Response.Close();
                    }
                }
            }
            catch (Exception ex) {
                System.Console.WriteLine("!! {0}: {1}", ex.GetType().Name, ex.Message);
                throw;
            }
            finally {
                listener.BeginGetContext(OnContext, null);
            }
        }