Utilities/HttpServer.cs
author moel.mich
Sun, 28 Oct 2012 14:06:50 +0000
changeset 386 7094d5dd924b
parent 373 3b8443edb0e6
child 387 87093432c843
permissions -rw-r--r--
Changed the source formatting of the HttpServer class to match the rest of the project.
     1 /*
     2  
     3   This Source Code Form is subject to the terms of the Mozilla Public
     4   License, v. 2.0. If a copy of the MPL was not distributed with this
     5   file, You can obtain one at http://mozilla.org/MPL/2.0/.
     6  
     7 	Copyright (C) 2012 Prince Samuel <prince.samuel@gmail.com>
     8   Copyright (C) 2012 Michael Möller <mmoeller@openhardwaremonitor.org>
     9 
    10 */
    11 
    12 using System;
    13 using System.Drawing;
    14 using System.Drawing.Imaging;
    15 using System.IO;
    16 using System.Net;
    17 using System.Reflection;
    18 using System.Text;
    19 using System.Threading;
    20 using OpenHardwareMonitor.GUI;
    21 using OpenHardwareMonitor.Hardware;
    22 
    23 namespace OpenHardwareMonitor.Utilities {
    24 
    25   public class HttpServer {
    26     private HttpListener listener;
    27     private int listenerPort, nodeCount;
    28     private Thread listenerThread;
    29     private Node root;
    30 
    31     public HttpServer(Node r, int p) {
    32       root = r;
    33       listenerPort = p;
    34 
    35       //JSON node count. 
    36       nodeCount = 0;
    37       listener = new HttpListener();
    38     }
    39 
    40     public Boolean StartHTTPListener() {
    41       try {
    42         if (listener.IsListening)
    43           return true;
    44 
    45         string prefix = "http://+:" + listenerPort + "/";
    46         listener.Prefixes.Clear();
    47         listener.Prefixes.Add(prefix);
    48         listener.Start();
    49 
    50         if (listenerThread == null) {
    51           listenerThread = new Thread(HandleRequests);
    52           listenerThread.Start();
    53         }
    54       } catch (Exception) {
    55         return false;
    56       }
    57 
    58       return true;
    59     }
    60 
    61     public Boolean StopHTTPListener() {
    62       try {
    63         listenerThread.Abort();
    64         listener.Stop();
    65         listenerThread = null;
    66       } catch (HttpListenerException) {
    67       } catch (ThreadAbortException) {
    68       } catch (NullReferenceException) {
    69       } catch (Exception) {
    70       }
    71       return true;
    72     }
    73 
    74     public void HandleRequests() {
    75 
    76       while (listener.IsListening) {
    77         var context = listener.BeginGetContext(
    78           new AsyncCallback(ListenerCallback), listener);
    79         context.AsyncWaitHandle.WaitOne();
    80       }
    81     }
    82 
    83     public void ListenerCallback(IAsyncResult result) {
    84       HttpListener listener = (HttpListener)result.AsyncState;
    85       if (listener == null || !listener.IsListening)
    86         return;
    87       // Call EndGetContext to complete the asynchronous operation.
    88       HttpListenerContext context = listener.EndGetContext(result);
    89       HttpListenerRequest request = context.Request;
    90 
    91       var requestedFile = request.RawUrl.Substring(1);
    92       if (requestedFile == "data.json") {
    93         SendJSON(context);
    94         return;
    95       }
    96 
    97       if (requestedFile.Contains("images_icon")) {
    98         ServeResourceImage(context, requestedFile.Replace("images_icon/", ""));
    99         return;
   100       }
   101 
   102       // default file to be served
   103       if (string.IsNullOrEmpty(requestedFile))
   104         requestedFile = "index.html";
   105 
   106       string[] splits = requestedFile.Split('.');
   107       string ext = splits[splits.Length - 1];
   108       ServeResourceFile(context, "Web." + requestedFile.Replace('/', '.'), ext);
   109     }
   110 
   111     private void ServeResourceFile(HttpListenerContext context, string name, 
   112       string ext) 
   113     {
   114 
   115       // resource names do not support the hyphen
   116       name = "OpenHardwareMonitor.Resources." + 
   117         name.Replace("custom-theme", "custom_theme");
   118 
   119       string[] names =
   120         Assembly.GetExecutingAssembly().GetManifestResourceNames();
   121       for (int i = 0; i < names.Length; i++) {
   122         if (names[i].Replace('\\', '.') == name) {
   123           using (Stream stream = Assembly.GetExecutingAssembly().
   124             GetManifestResourceStream(names[i])) {
   125             context.Response.ContentType = GetcontentType("." + ext);
   126             context.Response.ContentLength64 = stream.Length;
   127             byte[] buffer = new byte[512 * 1024];
   128             int len;
   129             while ((len = stream.Read(buffer, 0, buffer.Length)) > 0) {
   130               context.Response.OutputStream.Write(buffer, 0, len);
   131             }
   132             context.Response.OutputStream.Close();
   133           }
   134           return;
   135         }
   136       }
   137       context.Response.OutputStream.Close();
   138       context.Response.StatusCode = 404;
   139       context.Response.Close();
   140     }
   141 
   142     private void ServeResourceImage(HttpListenerContext context, string name) {
   143       name = "OpenHardwareMonitor.Resources." + name;
   144 
   145       string[] names =
   146         Assembly.GetExecutingAssembly().GetManifestResourceNames();
   147       for (int i = 0; i < names.Length; i++) {
   148         if (names[i].Replace('\\', '.') == name) {
   149           using (Stream stream = Assembly.GetExecutingAssembly().
   150             GetManifestResourceStream(names[i])) {
   151 
   152             Image image = Image.FromStream(stream);
   153             context.Response.ContentType = "image/png";
   154             using (MemoryStream ms = new MemoryStream()) {
   155               image.Save(ms, ImageFormat.Png);
   156               ms.WriteTo(context.Response.OutputStream);
   157             }
   158             context.Response.OutputStream.Close();
   159             image.Dispose();
   160             return;
   161           }
   162         }
   163       }
   164       context.Response.OutputStream.Close();
   165       context.Response.StatusCode = 404;
   166       context.Response.Close();
   167     }
   168 
   169     private void SendJSON(HttpListenerContext context) {
   170 
   171       string JSON = "{\"id\": 0, \"Text\": \"Sensor\", \"Children\": [";
   172       nodeCount = 1;
   173       JSON += GenerateJSON(root);
   174       JSON += "]";
   175       JSON += ", \"Min\": \"Min\"";
   176       JSON += ", \"Value\": \"Value\"";
   177       JSON += ", \"Max\": \"Max\"";
   178       JSON += ", \"ImageURL\": \"\"";
   179       JSON += "}";
   180 
   181       var responseContent = JSON;
   182       byte[] buffer = Encoding.UTF8.GetBytes(responseContent);
   183 
   184       context.Response.ContentLength64 = buffer.Length;
   185       context.Response.ContentType = "application/json";
   186 
   187       Stream outputStream = context.Response.OutputStream;
   188       outputStream.Write(buffer, 0, buffer.Length);
   189       outputStream.Close();
   190 
   191     }
   192 
   193     private string GenerateJSON(Node n) {
   194       string JSON = "{\"id\": " + nodeCount + ", \"Text\": \"" + n.Text 
   195         + "\", \"Children\": [";
   196       nodeCount++;
   197 
   198       foreach (Node child in n.Nodes)
   199         JSON += GenerateJSON(child) + ", ";
   200       if (JSON.EndsWith(", "))
   201         JSON = JSON.Remove(JSON.LastIndexOf(","));
   202       JSON += "]";
   203 
   204       if (n is SensorNode) {
   205         JSON += ", \"Min\": \"" + ((SensorNode)n).Min + "\"";
   206         JSON += ", \"Value\": \"" + ((SensorNode)n).Value + "\"";
   207         JSON += ", \"Max\": \"" + ((SensorNode)n).Max + "\"";
   208         JSON += ", \"ImageURL\": \"images/transparent.png\"";
   209       } else if (n is HardwareNode) {
   210         JSON += ", \"Min\": \"\"";
   211         JSON += ", \"Value\": \"\"";
   212         JSON += ", \"Max\": \"\"";
   213         JSON += ", \"ImageURL\": \"images_icon/" + 
   214           GetHardwareImageFile((HardwareNode)n) + "\"";
   215       } else if (n is TypeNode) {
   216         JSON += ", \"Min\": \"\"";
   217         JSON += ", \"Value\": \"\"";
   218         JSON += ", \"Max\": \"\"";
   219         JSON += ", \"ImageURL\": \"images_icon/" + 
   220           GetTypeImageFile((TypeNode)n) + "\"";
   221       } else {
   222         JSON += ", \"Min\": \"\"";
   223         JSON += ", \"Value\": \"\"";
   224         JSON += ", \"Max\": \"\"";
   225         JSON += ", \"ImageURL\": \"images_icon/computer.png\"";
   226       }
   227 
   228       JSON += "}";
   229       return JSON;
   230     }
   231 
   232     private static void ReturnFile(HttpListenerContext context, string filePath) 
   233     {
   234       context.Response.ContentType = 
   235         GetcontentType(Path.GetExtension(filePath));
   236       const int bufferSize = 1024 * 512; //512KB
   237       var buffer = new byte[bufferSize];
   238       using (var fs = File.OpenRead(filePath)) {
   239 
   240         context.Response.ContentLength64 = fs.Length;
   241         int read;
   242         while ((read = fs.Read(buffer, 0, buffer.Length)) > 0)
   243           context.Response.OutputStream.Write(buffer, 0, read);
   244       }
   245 
   246       context.Response.OutputStream.Close();
   247     }
   248 
   249     private static string GetcontentType(string extension) {
   250       switch (extension) {
   251         case ".avi": return "video/x-msvideo";
   252         case ".css": return "text/css";
   253         case ".doc": return "application/msword";
   254         case ".gif": return "image/gif";
   255         case ".htm":
   256         case ".html": return "text/html";
   257         case ".jpg":
   258         case ".jpeg": return "image/jpeg";
   259         case ".js": return "application/x-javascript";
   260         case ".mp3": return "audio/mpeg";
   261         case ".png": return "image/png";
   262         case ".pdf": return "application/pdf";
   263         case ".ppt": return "application/vnd.ms-powerpoint";
   264         case ".zip": return "application/zip";
   265         case ".txt": return "text/plain";
   266         default: return "application/octet-stream";
   267       }
   268     }
   269 
   270     private static string GetHardwareImageFile(HardwareNode hn) {
   271 
   272       switch (hn.Hardware.HardwareType) {
   273         case HardwareType.CPU:
   274           return "cpu.png";
   275         case HardwareType.GpuNvidia:
   276           return "nvidia.png";
   277         case HardwareType.GpuAti:
   278           return "ati.png";
   279         case HardwareType.HDD:
   280           return "hdd.png";
   281         case HardwareType.Heatmaster:
   282           return "bigng.png";
   283         case HardwareType.Mainboard:
   284           return "mainboard.png";
   285         case HardwareType.SuperIO:
   286           return "chip.png";
   287         case HardwareType.TBalancer:
   288           return "bigng.png";
   289         case HardwareType.RAM:
   290           return "ram.png";
   291         default:
   292           return "cpu.png";
   293       }
   294 
   295     }
   296 
   297     private static string GetTypeImageFile(TypeNode tn) {
   298 
   299       switch (tn.SensorType) {
   300         case SensorType.Voltage:
   301           return "voltage.png";
   302         case SensorType.Clock:
   303           return "clock.png";
   304         case SensorType.Load:
   305           return "load.png";
   306         case SensorType.Temperature:
   307           return "temperature.png";
   308         case SensorType.Fan:
   309           return "fan.png";
   310         case SensorType.Flow:
   311           return "flow.png";
   312         case SensorType.Control:
   313           return "control.png";
   314         case SensorType.Level:
   315           return "level.png";
   316         case SensorType.Power:
   317           return "power.png";
   318         default:
   319           return "power.png";
   320       }
   321 
   322     }
   323 
   324     public int ListenerPort {
   325       get { return listenerPort; }
   326       set { listenerPort = value; }
   327     }
   328 
   329     ~HttpServer() {
   330       StopHTTPListener();
   331       listener.Abort();
   332     }
   333 
   334     public void Quit() {
   335       StopHTTPListener();
   336       listener.Abort();
   337     }
   338   }
   339 }