diff -r d043dac9f34e -r d8fa1e55acfa Utilities/HttpServer.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Utilities/HttpServer.cs Sun May 27 20:15:32 2012 +0000 @@ -0,0 +1,371 @@ +/* + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + + Copyright (C) 2012 Prince Samuel + +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Net; +using System.Threading; +using System.IO; +using OpenHardwareMonitor.GUI; +using OpenHardwareMonitor.Hardware; +using System.Reflection; +using System.Drawing; +using System.Drawing.Imaging; + +namespace OpenHardwareMonitor.Utilities +{ + public class HttpServer + { + private HttpListener listener; + private int listenerPort, nodeCount; + private Thread listenerThread; + private Node root; + + public HttpServer(Node r, int p) + { + root = r; + listenerPort = p; + //JSON node count. + nodeCount = 0; + listener = new HttpListener(); + } + + public Boolean startHTTPListener() + { + try + { + if (listener.IsListening) + return true; + + string prefix = "http://+:" + listenerPort + "/"; + listener.Prefixes.Clear(); + listener.Prefixes.Add(prefix); + listener.Start(); + + if (listenerThread == null) + { + listenerThread = new Thread(HandleRequests); + listenerThread.Start(); + } + } + catch (Exception e) + { + return false; + } + + return true; + } + + public Boolean stopHTTPListener() + { + try + { + listenerThread.Abort(); + listener.Stop(); + listenerThread = null; + } + catch (System.Net.HttpListenerException e) + { + } + catch (System.Threading.ThreadAbortException e) + { + } + catch (System.NullReferenceException e) + { + } + catch (Exception e) + { + } + return true; + } + + public void HandleRequests() + { + + while (listener.IsListening) + { + var context = listener.BeginGetContext(new AsyncCallback(ListenerCallback), listener); + context.AsyncWaitHandle.WaitOne(); + } + } + + public void ListenerCallback(IAsyncResult result) + { + HttpListener listener = (HttpListener)result.AsyncState; + if (listener == null || !listener.IsListening) + return; + // Call EndGetContext to complete the asynchronous operation. + HttpListenerContext context = listener.EndGetContext(result); + HttpListenerRequest request = context.Request; + + var requestedFile = request.RawUrl.Substring(1); + if (requestedFile == "data.json") + { + sendJSON(context); + return; + } + + if (requestedFile.Contains("images_icon")) + { + serveResourceImage(context, requestedFile.Replace("images_icon/", "")); + return; + } + + //default file to be served + if (string.IsNullOrEmpty(requestedFile)) + requestedFile = "index.html"; + + string[] splits = requestedFile.Split('.'); + string ext = splits[splits.Length - 1]; + serveResourceFile(context, "Web." + requestedFile.Replace('/', '.'), ext); + } + + private void serveResourceFile(HttpListenerContext context ,string name, string ext) { + + //hack! resource names do not support the hyphen + name = "OpenHardwareMonitor.Resources." + name.Replace("custom-theme", "custom_theme"); + + string[] names = + Assembly.GetExecutingAssembly().GetManifestResourceNames(); + for (int i = 0; i < names.Length; i++) { + if (names[i].Replace('\\', '.') == name) { + using (Stream stream = Assembly.GetExecutingAssembly(). + GetManifestResourceStream(names[i])) { + context.Response.ContentType = getcontentType("." + ext); + context.Response.ContentLength64 = stream.Length; + byte[] buffer = new byte[512 * 1024]; + int len; + while ((len = stream.Read(buffer, 0, buffer.Length)) > 0) + { + context.Response.OutputStream.Write(buffer, 0, len); + } + context.Response.OutputStream.Close(); + } + return; + } + } + context.Response.OutputStream.Close(); + context.Response.StatusCode = 404; + context.Response.Close(); + } + + private void serveResourceImage(HttpListenerContext context ,string name) { + name = "OpenHardwareMonitor.Resources." + name; + + string[] names = + Assembly.GetExecutingAssembly().GetManifestResourceNames(); + for (int i = 0; i < names.Length; i++) { + if (names[i].Replace('\\', '.') == name) { + using (Stream stream = Assembly.GetExecutingAssembly(). + GetManifestResourceStream(names[i])) { + + Image image = Image.FromStream(stream); + context.Response.ContentType = "image/png"; + using (MemoryStream ms = new MemoryStream()) + { + image.Save(ms, ImageFormat.Png); + ms.WriteTo(context.Response.OutputStream); + } + context.Response.OutputStream.Close(); + image.Dispose(); + return; + } + } + } + context.Response.OutputStream.Close(); + context.Response.StatusCode = 404; + context.Response.Close(); + } + + private void sendJSON(HttpListenerContext context) + { + + string JSON = "{\"id\": 0, \"Text\": \"Sensor\", \"Children\": ["; + nodeCount = 1; + JSON += generateJSON(root); + JSON += "]"; + JSON += ", \"Min\": \"Min\""; + JSON += ", \"Value\": \"Value\""; + JSON += ", \"Max\": \"Max\""; + JSON += ", \"ImageURL\": \"\""; + JSON += "}"; + + var responseContent = JSON; + byte[] buffer = Encoding.UTF8.GetBytes(responseContent); + + context.Response.ContentLength64 = buffer.Length; + context.Response.ContentType = "application/json"; + + Stream outputStream = context.Response.OutputStream; + outputStream.Write(buffer, 0, buffer.Length); + outputStream.Close(); + + } + + private string generateJSON(Node n) + { + string JSON = "{\"id\": " + nodeCount + ", \"Text\": \"" + n.Text + "\", \"Children\": ["; + nodeCount++; + + foreach (Node child in n.Nodes) + JSON += generateJSON(child) + ", "; + if (JSON.EndsWith(", ")) + JSON = JSON.Remove(JSON.LastIndexOf(",")); + JSON += "]"; + + if (n is SensorNode) + { + JSON += ", \"Min\": \"" + ((SensorNode)n).Min + "\""; + JSON += ", \"Value\": \"" + ((SensorNode)n).Value + "\""; + JSON += ", \"Max\": \"" + ((SensorNode)n).Max + "\""; + JSON += ", \"ImageURL\": \"images/transparent.png\""; + } + else if (n is HardwareNode) + { + JSON += ", \"Min\": \"\""; + JSON += ", \"Value\": \"\""; + JSON += ", \"Max\": \"\""; + JSON += ", \"ImageURL\": \"images_icon/" + getHardwareImageFile((HardwareNode)n) + "\""; + } + else if (n is TypeNode) + { + JSON += ", \"Min\": \"\""; + JSON += ", \"Value\": \"\""; + JSON += ", \"Max\": \"\""; + JSON += ", \"ImageURL\": \"images_icon/" + getTypeImageFile((TypeNode)n) + "\""; + } + else + { + JSON += ", \"Min\": \"\""; + JSON += ", \"Value\": \"\""; + JSON += ", \"Max\": \"\""; + JSON += ", \"ImageURL\": \"images_icon/computer.png\""; + } + + JSON += "}"; + return JSON; + } + + private static void returnFile(HttpListenerContext context, string filePath) + { + context.Response.ContentType = getcontentType(Path.GetExtension(filePath)); + const int bufferSize = 1024 * 512; //512KB + var buffer = new byte[bufferSize]; + using (var fs = File.OpenRead(filePath)) + { + + context.Response.ContentLength64 = fs.Length; + int read; + while ((read = fs.Read(buffer, 0, buffer.Length)) > 0) + context.Response.OutputStream.Write(buffer, 0, read); + } + + context.Response.OutputStream.Close(); + } + + private static string getcontentType(string extension) + { + switch (extension) + { + case ".avi": return "video/x-msvideo"; + case ".css": return "text/css"; + case ".doc": return "application/msword"; + case ".gif": return "image/gif"; + case ".htm": + case ".html": return "text/html"; + case ".jpg": + case ".jpeg": return "image/jpeg"; + case ".js": return "application/x-javascript"; + case ".mp3": return "audio/mpeg"; + case ".png": return "image/png"; + case ".pdf": return "application/pdf"; + case ".ppt": return "application/vnd.ms-powerpoint"; + case ".zip": return "application/zip"; + case ".txt": return "text/plain"; + default: return "application/octet-stream"; + } + } + + private static string getHardwareImageFile(HardwareNode hn) + { + + switch (hn.Hardware.HardwareType) + { + case HardwareType.CPU: + return "cpu.png"; + case HardwareType.GpuNvidia: + return "nvidia.png"; + case HardwareType.GpuAti: + return "ati.png"; + case HardwareType.HDD: + return "hdd.png"; + case HardwareType.Heatmaster: + return "bigng.png"; + case HardwareType.Mainboard: + return "mainboard.png"; + case HardwareType.SuperIO: + return "chip.png"; + case HardwareType.TBalancer: + return "bigng.png"; + default: + return "cpu.png"; + } + + } + + private static string getTypeImageFile(TypeNode tn) + { + + switch (tn.SensorType) + { + case SensorType.Voltage: + return "voltage.png"; + case SensorType.Clock: + return "clock.png"; + case SensorType.Load: + return "load.png"; + case SensorType.Temperature: + return "temperature.png"; + case SensorType.Fan: + return "fan.png"; + case SensorType.Flow: + return "flow.png"; + case SensorType.Control: + return "control.png"; + case SensorType.Level: + return "level.png"; + case SensorType.Power: + return "power.png"; + default: + return "power.png"; + } + + } + + public int ListenerPort + { + get { return listenerPort; } + set { listenerPort = value; } + } + + ~HttpServer() + { + stopHTTPListener(); + listener.Abort(); + } + + public void Quit() + { + stopHTTPListener(); + listener.Abort(); + } + } +}