OSDN Git Service

報告書に関する設定を行うダイアログを実装する
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / LogServer.cs
1 using System;\r
2 using System.IO;\r
3 using System.Net;\r
4 using System.Net.Sockets;\r
5 using System.Text;\r
6 using System.Threading;\r
7 using System.Web;\r
8 using System.Windows.Forms;\r
9 \r
10 namespace KancolleSniffer\r
11 {\r
12     public class LogServer\r
13     {\r
14         private readonly TcpListener _listener;\r
15         private readonly Thread _thread;\r
16         private readonly string _indexDir = Path.GetDirectoryName(Application.ExecutablePath);\r
17         private string _outputDir = Path.GetDirectoryName(Application.ExecutablePath);\r
18 \r
19         public string OutputDir\r
20         {\r
21             set { _outputDir = value; }\r
22         }\r
23 \r
24         public LogServer(int port)\r
25         {\r
26             _listener = new TcpListener(IPAddress.Loopback, port);\r
27             _thread = new Thread(Listen);\r
28         }\r
29 \r
30         public void Start()\r
31         {\r
32             _thread.Start();\r
33         }\r
34 \r
35         private void Listen()\r
36         {\r
37             try\r
38             {\r
39                 _listener.Start();\r
40                 while (true)\r
41                 {\r
42                     var data = new byte[4096];\r
43                     var client = _listener.AcceptSocket();\r
44                     try\r
45                     {\r
46                         if (client.Available == 0)\r
47                         {\r
48                             Thread.Sleep(500);\r
49                             if (client.Available == 0)\r
50                                 continue;\r
51                         }\r
52                         if (client.Receive(data) == 0)\r
53                             continue;\r
54                         var request = Encoding.UTF8.GetString(data).Split('\r')[0].Split(' ');\r
55                         if (request.Length != 3)\r
56                         {\r
57                             SendError(client, "400 Bad Request");\r
58                             continue;\r
59                         }\r
60                         if (!request[0].StartsWith("GET", StringComparison.OrdinalIgnoreCase))\r
61                         {\r
62                             SendError(client, "501 Not Implemented");\r
63                             continue;\r
64                         }\r
65                         var path = HttpUtility.UrlDecode(request[1].Split('?')[0]);\r
66                         if (path == null || !path.StartsWith("/"))\r
67                         {\r
68                             SendError(client, "400 Bad Request");\r
69                             continue;\r
70                         }\r
71 \r
72                         path = path == "/" ? "index.html" : path.Substring(1);\r
73                         var full = Path.Combine(_indexDir, path);\r
74                         var csv = Path.Combine(_outputDir, path);\r
75                         if (path.EndsWith(".html", StringComparison.OrdinalIgnoreCase) && File.Exists(full))\r
76                         {\r
77                             SendFile(client, full, "text/html");\r
78                             continue;\r
79                         }\r
80                         if (path.EndsWith(".csv", StringComparison.OrdinalIgnoreCase) && File.Exists(csv))\r
81                         {\r
82                             SendFile(client, csv, "text/csv; charset=Shift_JIS");\r
83                             continue;\r
84                         }\r
85                         if (path.EndsWith(".js", StringComparison.OrdinalIgnoreCase) && File.Exists(full))\r
86                         {\r
87                             SendFile(client, full, "application/javascript");\r
88                             continue;\r
89                         }\r
90                         SendError(client, "404 Not Found");\r
91                     }\r
92                     catch (IOException)\r
93                     {\r
94                     }\r
95                     catch (InvalidOperationException)\r
96                     {\r
97                     }\r
98                     finally\r
99                     {\r
100                         client.Close();\r
101                     }\r
102                 }\r
103             }\r
104             catch (SocketException)\r
105             {\r
106             }\r
107             finally\r
108             {\r
109                 _listener.Stop();\r
110             }\r
111         }\r
112 \r
113         private void SendError(Socket client, string error)\r
114         {\r
115             using (var writer = new StreamWriter(new MemoryStream(), Encoding.ASCII))\r
116             {\r
117                 writer.Write("HTTP/1.1 {0}\r\n", error);\r
118                 writer.Write("Server: KancolleSniffer\r\n");\r
119                 writer.Write("Date: {0:R}\r\n", DateTime.Now);\r
120                 writer.Write("Connection: close\r\n\r\n");\r
121                 writer.Write("<html><head><title>{0}</title></head>\r\n", error);\r
122                 writer.Write("<body><h4>{0}</h4></body></html>\r\n\r\n", error);\r
123                 writer.Flush();\r
124                 client.Send(((MemoryStream)writer.BaseStream).ToArray());\r
125             }\r
126         }\r
127 \r
128         private void SendFile(Socket client, string path, string mime)\r
129         {\r
130             using (var writer = new StreamWriter(new MemoryStream(), Encoding.ASCII))\r
131             {\r
132                 writer.Write("HTTP/1.1 200 OK\r\n");\r
133                 writer.Write("Server: KancolleSniffer\r\n");\r
134                 writer.Write("Date: {0:R}\r\n", DateTime.Now);\r
135                 writer.Write("Content-Length: {0}\r\n", new FileInfo(path).Length);\r
136                 writer.Write("Content-Type: {0}\r\n", mime);\r
137                 writer.Write("Connection: close\r\n\r\n");\r
138                 writer.Flush();\r
139                 client.SendFile(path, ((MemoryStream)writer.BaseStream).ToArray(), null, TransmitFileOptions.UseDefaultWorkerThread);\r
140             }\r
141         }\r
142 \r
143         public void Stop()\r
144         {\r
145             _listener.Stop();\r
146             _thread.Join();\r
147         }\r
148     }\r
149 }