| 47 | | } |
| 48 | | |
| 49 | | public static Context CreateContext(TcpClient tcpClient) |
| 50 | | { |
| 51 | | Context ctx = new Context(); |
| 52 | | HttpWebRequest webRequest = HttpWebRequest.Create(String.Format("http://localhost:{0}/{1}", ((IPEndPoint)tcpClient.Client.LocalEndPoint).Port, parts[1])); |
| 53 | | |
| 54 | | while ((line = sr.ReadLine()) != null) |
| 55 | | { |
| 56 | | if (line == "") |
| 57 | | { |
| 58 | | break; |
| 59 | | } |
| 60 | | if (isFirstLine) |
| 61 | | { |
| 62 | | String[] parts = line.Split(new Char[] { ' ' }, 3); |
| 63 | | |
| 64 | | if (parts.Length != 3) |
| 65 | | throw new WebException("Invalid Request", WebExceptionStatus.ProtocolError); |
| 66 | | |
| 67 | | } |
| 68 | | |
| 69 | | isFirstLine = false; |
| 70 | | } |
| 71 | | |
| 72 | | } |
| 73 | | } |
| 74 | | |
| 75 | | delegate void RequestEventHandler(Context ctx); |
| 76 | | class SingleThreadServer |
| 77 | | { |
| 78 | | private TcpListener _tcpListener; |
| 79 | | private Boolean _isRunning = false; |
| 80 | | |
| 81 | | public event RequestEventHandler Request; |
| 82 | | |
| 83 | | public Boolean IsRunning |
| 84 | | { |
| 85 | | get |
| 86 | | { |
| 87 | | return _isRunning; |
| 88 | | } |
| 89 | | } |
| 90 | | |
| 91 | | protected void OnRequest(Context ctx) |
| 92 | | { |
| 93 | | if (Request != null) |
| 94 | | Request(ctx); |
| 95 | | } |
| 96 | | |
| 97 | | private void HandleRequest(TcpClient tcpClient) |
| 98 | | { |
| 99 | | Stream stream = tcpClient.GetStream(); |
| 100 | | StreamWriter sw = new StreamWriter(stream); |
| 101 | | StreamReader sr = new StreamReader(stream); |
| 102 | | |
| 103 | | String text = ""; |
| 104 | | String line; |
| 105 | | Boolean isFirstLine = true; |
| 106 | | Context ctx = Context.CreateContext(tcpClient); |
| 107 | | Trace.WriteLine(line, "access"); |
| 108 | | |
| 109 | | |
| 110 | | MemoryStream writer = new MemoryStream(); |
| 111 | | |
| 112 | | try |
| 113 | | { |
| 114 | | Byte[] contentBytes = Encoding.UTF8.GetBytes(String.Format("<title>200 OK - Ircv+httpd</title><form action='' method='GET'><input type='text' name='s' value='{0}'><input type='submit'></form>", System.Web.HttpUtility.HtmlEncode(text))); |
| 115 | | writer.Write(contentBytes, 0, contentBytes.Length); |
| 116 | | } |
| 117 | | catch (IOException e) |
| 118 | | { |
| 119 | | //writer.Write(e.ToString()); |
| 120 | | } |
| 121 | | writer.Flush(); |
| 122 | | |
| 123 | | Byte[] bytes = writer.ToArray(); |
| 124 | | sw.WriteLine("HTTP/1.0 200 OK"); |
| 125 | | sw.WriteLine("Content-Type: text/html; charset=utf-8"); |
| 126 | | sw.WriteLine("Content-Length: {0}", bytes.LongLength); |
| 127 | | sw.WriteLine("Connection: close"); |
| 128 | | |
| 129 | | sw.WriteLine(); |
| 130 | | sw.Flush(); |
| 131 | | sw.BaseStream.Write(bytes, 0, bytes.Length); |
| 132 | | |
| 133 | | //sw.WriteLine("{0}", DateTime.Now); |
| 134 | | //Trace.WriteLine("Response OK", "access"); |
| 135 | | //Console.WriteLine(writer.ToString()); |
| 136 | | //stream.Flush(); |
| 137 | | |
| 138 | | //sw.Close(); |
| 139 | | //sr.Close(); |
| 140 | | |
| 141 | | //tcpClient.Client.Shutdown(SocketShutdown.Both); |
| 142 | | tcpClient.Client.BeginDisconnect(false, null, null); |
| 143 | | //stream.Close(); |
| 144 | | } |
| 145 | | |
| 146 | | public void Start(IPEndPoint endPoint) |
| 147 | | { |
| 148 | | _tcpListener = new TcpListener(endPoint); |
| 149 | | //_AcceptTcpClientCallback = new AsyncCallback(AcceptTcpClientCallback); |
| 150 | | _tcpListener.Start(); |
| 151 | | //_tcpListener.BeginAcceptTcpClient(_AcceptTcpClientCallback, _tcpListener); |
| 152 | | _isRunning = true; |
| 153 | | TcpClient tcpClient; |
| 154 | | while ((tcpClient = _tcpListener.AcceptTcpClient()) != null) |
| 155 | | { |
| 156 | | try |
| 157 | | { |
| 158 | | HandleRequest(tcpClient); |
| 159 | | } |
| 160 | | catch (Exception e) |
| 161 | | { |
| 162 | | Trace.WriteLine(e.Message, "error"); |
| 163 | | } |
| 164 | | } |
| 165 | | } |
| 166 | | |
| 167 | | private AsyncCallback _AcceptTcpClientCallback; |
| 168 | | private void AcceptTcpClientCallback(IAsyncResult ar) |
| 169 | | { |
| 170 | | //TcpListener tcpListener = ar.AsyncState as TcpListener; |
| 171 | | TcpClient tcpClient = _tcpListener.EndAcceptTcpClient(ar); |
| 172 | | _tcpListener.BeginAcceptTcpClient(_AcceptTcpClientCallback, _tcpListener); |
| 173 | | try |
| 174 | | { |
| 175 | | HandleRequest(tcpClient); |
| 176 | | } |
| 177 | | catch (Exception e) |
| 178 | | { |
| 179 | | Trace.WriteLine(e.Message, "error"); |
| 180 | | } |
| 181 | | //Trace.WriteLine("Response Done", "debug"); |
| 182 | | |
| 183 | | } |
| 184 | | |
| 185 | | public void Stop() |
| 186 | | { |
| 187 | | _tcpListener.Stop(); |
| 188 | | } |
| 189 | | } |
| 190 | | |
| 191 | | class LoggingTraceListener : ConsoleTraceListener |
| 192 | | { |
| 193 | | public override void Write(string message) |
| 194 | | { |
| 195 | | base.Write(String.Format("{0} {1}", DateTime.Now, message)); |
| 196 | | } |
| 197 | | |
| 198 | | public override void WriteLine(string message) |
| 199 | | { |
| 200 | | base.WriteLine(String.Format("{0} {1}", DateTime.Now, message)); |
| 201 | | } |
| 202 | | |
| 203 | | public override void Write(string message, string category) |
| 204 | | { |
| 205 | | ConsoleColor color = Console.ForegroundColor; |
| 206 | | switch (category.ToLower()) |
| 207 | | { |
| 208 | | case "debug": |
| 209 | | case "info": |
| 210 | | Console.ForegroundColor = ConsoleColor.White; |
| 211 | | break; |
| 212 | | case "warn": |
| 213 | | Console.ForegroundColor = ConsoleColor.Yellow; |
| 214 | | break; |
| 215 | | case "error": |
| 216 | | Console.ForegroundColor = ConsoleColor.Red; |
| 217 | | break; |
| 218 | | case "notice": |
| 219 | | break; |
| 220 | | } |
| 221 | | this.Write(String.Format("[{0}] {1}", category, message)); |
| 222 | | Console.ForegroundColor = color; |
| 223 | | } |
| 224 | | |
| 225 | | public override void WriteLine(string message, string category) |
| 226 | | { |
| 227 | | this.Write(message, category); |
| 228 | | base.WriteLine(""); |