Utilities/HttpServer.cs
author StephaneLenclud
Thu, 18 Apr 2013 23:25:10 +0200
branchMiniDisplay
changeset 444 9b09e2ee0968
parent 387 87093432c843
permissions -rw-r--r--
Front View plug-in does not init if no sensor added.
Fixing some format to make strings shorter.
Now trying to start SoundGraphAccess.exe process from same directory.
Packed mode now can display three sensors along with the current time.
     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-2013 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 node, int port) {
    32       root = node;
    33       listenerPort = port;
    34 
    35       //JSON node count. 
    36       nodeCount = 0;
    37 
    38       try {
    39         listener = new HttpListener();
    40         listener.IgnoreWriteExceptions = true;
    41       } catch (PlatformNotSupportedException) {
    42         listener = null;
    43       }
    44     }
    45 
    46     public bool PlatformNotSupported {
    47       get {
    48         return listener == null;
    49       }
    50     }
    51 
    52     public Boolean StartHTTPListener() {
    53       if (PlatformNotSupported)
    54         return false;
    55 
    56       try {
    57         if (listener.IsListening)
    58           return true;
    59 
    60         string prefix = "http://+:" + listenerPort + "/";
    61         listener.Prefixes.Clear();
    62         listener.Prefixes.Add(prefix);
    63         listener.Start();
    64 
    65         if (listenerThread == null) {
    66           listenerThread = new Thread(HandleRequests);
    67           listenerThread.Start();
    68         }
    69       } catch (Exception) {
    70         return false;
    71       }
    72 
    73       return true;
    74     }
    75 
    76     public Boolean StopHTTPListener() {
    77       if (PlatformNotSupported)
    78         return false;
    79 
    80       try {
    81         listenerThread.Abort();
    82         listener.Stop();
    83         listenerThread = null;
    84       } catch (HttpListenerException) {
    85       } catch (ThreadAbortException) {
    86       } catch (NullReferenceException) {
    87       } catch (Exception) {
    88       }
    89       return true;
    90     }
    91 
    92     private void HandleRequests() {
    93 
    94       while (listener.IsListening) {
    95         var context = listener.BeginGetContext(
    96           new AsyncCallback(ListenerCallback), listener);
    97         context.AsyncWaitHandle.WaitOne();
    98       }
    99     }
   100 
   101     private void ListenerCallback(IAsyncResult result) {
   102       HttpListener listener = (HttpListener)result.AsyncState;
   103       if (listener == null || !listener.IsListening)
   104         return;
   105 
   106       // Call EndGetContext to complete the asynchronous operation.
   107       HttpListenerContext context;
   108       try {
   109         context = listener.EndGetContext(result);     
   110       } catch (Exception) {
   111         return;
   112       }
   113 
   114       HttpListenerRequest request = context.Request;
   115 
   116       var requestedFile = request.RawUrl.Substring(1);
   117       if (requestedFile == "data.json") {
   118         SendJSON(context.Response);
   119         return;
   120       }
   121 
   122       if (requestedFile.Contains("images_icon")) {
   123         ServeResourceImage(context.Response, 
   124           requestedFile.Replace("images_icon/", ""));
   125         return;
   126       }
   127 
   128       // default file to be served
   129       if (string.IsNullOrEmpty(requestedFile))
   130         requestedFile = "index.html";
   131 
   132       string[] splits = requestedFile.Split('.');
   133       string ext = splits[splits.Length - 1];
   134       ServeResourceFile(context.Response, 
   135         "Web." + requestedFile.Replace('/', '.'), ext);
   136     }
   137 
   138     private void ServeResourceFile(HttpListenerResponse response, string name, 
   139       string ext) 
   140     {
   141       // resource names do not support the hyphen
   142       name = "OpenHardwareMonitor.Resources." + 
   143         name.Replace("custom-theme", "custom_theme");
   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             response.ContentType = GetcontentType("." + ext);
   152             response.ContentLength64 = stream.Length;
   153             byte[] buffer = new byte[512 * 1024];
   154             int len;
   155             try {
   156               Stream output = response.OutputStream;
   157               while ((len = stream.Read(buffer, 0, buffer.Length)) > 0) {
   158                 output.Write(buffer, 0, len);
   159               }
   160               output.Flush();
   161               output.Close();              
   162               response.Close();
   163             } catch (HttpListenerException) { 
   164             } catch (InvalidOperationException) { 
   165             }
   166             return;
   167           }          
   168         }
   169       }
   170 
   171       response.StatusCode = 404;
   172       response.Close();
   173     }
   174 
   175     private void ServeResourceImage(HttpListenerResponse response, string name) {
   176       name = "OpenHardwareMonitor.Resources." + name;
   177 
   178       string[] names =
   179         Assembly.GetExecutingAssembly().GetManifestResourceNames();
   180       for (int i = 0; i < names.Length; i++) {
   181         if (names[i].Replace('\\', '.') == name) {
   182           using (Stream stream = Assembly.GetExecutingAssembly().
   183             GetManifestResourceStream(names[i])) {
   184 
   185             Image image = Image.FromStream(stream);
   186             response.ContentType = "image/png";
   187             try {
   188               Stream output = response.OutputStream;
   189               using (MemoryStream ms = new MemoryStream()) {
   190                 image.Save(ms, ImageFormat.Png);
   191                 ms.WriteTo(output);
   192               }
   193               output.Close();
   194             } catch (HttpListenerException) {              
   195             }
   196             image.Dispose();
   197             response.Close();
   198             return;
   199           }
   200         }
   201       }
   202 
   203       response.StatusCode = 404;
   204       response.Close();
   205     }
   206 
   207     private void SendJSON(HttpListenerResponse response) {
   208 
   209       string JSON = "{\"id\": 0, \"Text\": \"Sensor\", \"Children\": [";
   210       nodeCount = 1;
   211       JSON += GenerateJSON(root);
   212       JSON += "]";
   213       JSON += ", \"Min\": \"Min\"";
   214       JSON += ", \"Value\": \"Value\"";
   215       JSON += ", \"Max\": \"Max\"";
   216       JSON += ", \"ImageURL\": \"\"";
   217       JSON += "}";
   218 
   219       var responseContent = JSON;
   220       byte[] buffer = Encoding.UTF8.GetBytes(responseContent);
   221 
   222       response.AddHeader("Cache-Control", "no-cache");
   223 
   224       response.ContentLength64 = buffer.Length;
   225       response.ContentType = "application/json";
   226 
   227       try {
   228         Stream output = response.OutputStream;
   229         output.Write(buffer, 0, buffer.Length);
   230         output.Close();
   231       } catch (HttpListenerException) {
   232       }
   233 
   234       response.Close();
   235     }
   236 
   237     private string GenerateJSON(Node n) {
   238       string JSON = "{\"id\": " + nodeCount + ", \"Text\": \"" + n.Text 
   239         + "\", \"Children\": [";
   240       nodeCount++;
   241 
   242       foreach (Node child in n.Nodes)
   243         JSON += GenerateJSON(child) + ", ";
   244       if (JSON.EndsWith(", "))
   245         JSON = JSON.Remove(JSON.LastIndexOf(","));
   246       JSON += "]";
   247 
   248       if (n is SensorNode) {
   249         JSON += ", \"Min\": \"" + ((SensorNode)n).Min + "\"";
   250         JSON += ", \"Value\": \"" + ((SensorNode)n).Value + "\"";
   251         JSON += ", \"Max\": \"" + ((SensorNode)n).Max + "\"";
   252         JSON += ", \"ImageURL\": \"images/transparent.png\"";
   253       } else if (n is HardwareNode) {
   254         JSON += ", \"Min\": \"\"";
   255         JSON += ", \"Value\": \"\"";
   256         JSON += ", \"Max\": \"\"";
   257         JSON += ", \"ImageURL\": \"images_icon/" + 
   258           GetHardwareImageFile((HardwareNode)n) + "\"";
   259       } else if (n is TypeNode) {
   260         JSON += ", \"Min\": \"\"";
   261         JSON += ", \"Value\": \"\"";
   262         JSON += ", \"Max\": \"\"";
   263         JSON += ", \"ImageURL\": \"images_icon/" + 
   264           GetTypeImageFile((TypeNode)n) + "\"";
   265       } else {
   266         JSON += ", \"Min\": \"\"";
   267         JSON += ", \"Value\": \"\"";
   268         JSON += ", \"Max\": \"\"";
   269         JSON += ", \"ImageURL\": \"images_icon/computer.png\"";
   270       }
   271 
   272       JSON += "}";
   273       return JSON;
   274     }
   275 
   276     private static void ReturnFile(HttpListenerContext context, string filePath) 
   277     {
   278       context.Response.ContentType = 
   279         GetcontentType(Path.GetExtension(filePath));
   280       const int bufferSize = 1024 * 512; //512KB
   281       var buffer = new byte[bufferSize];
   282       using (var fs = File.OpenRead(filePath)) {
   283 
   284         context.Response.ContentLength64 = fs.Length;
   285         int read;
   286         while ((read = fs.Read(buffer, 0, buffer.Length)) > 0)
   287           context.Response.OutputStream.Write(buffer, 0, read);
   288       }
   289 
   290       context.Response.OutputStream.Close();
   291     }
   292 
   293     private static string GetcontentType(string extension) {
   294       switch (extension) {
   295         case ".avi": return "video/x-msvideo";
   296         case ".css": return "text/css";
   297         case ".doc": return "application/msword";
   298         case ".gif": return "image/gif";
   299         case ".htm":
   300         case ".html": return "text/html";
   301         case ".jpg":
   302         case ".jpeg": return "image/jpeg";
   303         case ".js": return "application/x-javascript";
   304         case ".mp3": return "audio/mpeg";
   305         case ".png": return "image/png";
   306         case ".pdf": return "application/pdf";
   307         case ".ppt": return "application/vnd.ms-powerpoint";
   308         case ".zip": return "application/zip";
   309         case ".txt": return "text/plain";
   310         default: return "application/octet-stream";
   311       }
   312     }
   313 
   314     private static string GetHardwareImageFile(HardwareNode hn) {
   315 
   316       switch (hn.Hardware.HardwareType) {
   317         case HardwareType.CPU:
   318           return "cpu.png";
   319         case HardwareType.GpuNvidia:
   320           return "nvidia.png";
   321         case HardwareType.GpuAti:
   322           return "ati.png";
   323         case HardwareType.HDD:
   324           return "hdd.png";
   325         case HardwareType.Heatmaster:
   326           return "bigng.png";
   327         case HardwareType.Mainboard:
   328           return "mainboard.png";
   329         case HardwareType.SuperIO:
   330           return "chip.png";
   331         case HardwareType.TBalancer:
   332           return "bigng.png";
   333         case HardwareType.RAM:
   334           return "ram.png";
   335         default:
   336           return "cpu.png";
   337       }
   338 
   339     }
   340 
   341     private static string GetTypeImageFile(TypeNode tn) {
   342 
   343       switch (tn.SensorType) {
   344         case SensorType.Voltage:
   345           return "voltage.png";
   346         case SensorType.Clock:
   347           return "clock.png";
   348         case SensorType.Load:
   349           return "load.png";
   350         case SensorType.Temperature:
   351           return "temperature.png";
   352         case SensorType.Fan:
   353           return "fan.png";
   354         case SensorType.Flow:
   355           return "flow.png";
   356         case SensorType.Control:
   357           return "control.png";
   358         case SensorType.Level:
   359           return "level.png";
   360         case SensorType.Power:
   361           return "power.png";
   362         default:
   363           return "power.png";
   364       }
   365 
   366     }
   367 
   368     public int ListenerPort {
   369       get { return listenerPort; }
   370       set { listenerPort = value; }
   371     }
   372 
   373     ~HttpServer() {
   374       if (PlatformNotSupported)
   375         return;
   376 
   377       StopHTTPListener();
   378       listener.Abort();
   379     }
   380 
   381     public void Quit() {
   382       if (PlatformNotSupported)
   383         return;
   384 
   385       StopHTTPListener();
   386       listener.Abort();
   387     }
   388   }
   389 }