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