using System; using System.IO; using System.Net.Sockets; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text; using Mono.Security.Protocol.Tls; namespace System.Net { // Token: 0x02000227 RID: 551 internal sealed class HttpConnection { // Token: 0x06001321 RID: 4897 RVA: 0x0003A48C File Offset: 0x0003868C public HttpConnection(global::System.Net.Sockets.Socket sock, EndPointListener epl, bool secure, global::System.Security.Cryptography.X509Certificates.X509Certificate2 cert, AsymmetricAlgorithm key) { this.sock = sock; this.epl = epl; this.secure = secure; this.key = key; if (!secure) { this.stream = new global::System.Net.Sockets.NetworkStream(sock, false); } else { SslServerStream sslServerStream = new SslServerStream(new global::System.Net.Sockets.NetworkStream(sock, false), cert, false, false); SslServerStream sslServerStream2 = sslServerStream; sslServerStream2.PrivateKeyCertSelectionDelegate = (PrivateKeySelectionCallback)Delegate.Combine(sslServerStream2.PrivateKeyCertSelectionDelegate, new PrivateKeySelectionCallback(this.OnPVKSelection)); this.stream = sslServerStream; } this.Init(); } // Token: 0x06001322 RID: 4898 RVA: 0x0003A514 File Offset: 0x00038714 private AsymmetricAlgorithm OnPVKSelection(X509Certificate certificate, string targetHost) { return this.key; } // Token: 0x06001323 RID: 4899 RVA: 0x0003A51C File Offset: 0x0003871C private void Init() { this.context_bound = false; this.i_stream = null; this.o_stream = null; this.prefix = null; this.chunked = false; this.ms = new MemoryStream(); this.position = 0; this.input_state = HttpConnection.InputState.RequestLine; this.line_state = HttpConnection.LineState.None; this.context = new HttpListenerContext(this); } // Token: 0x17000632 RID: 1586 // (get) Token: 0x06001324 RID: 4900 RVA: 0x0003A578 File Offset: 0x00038778 public int ChunkedUses { get { return this.chunked_uses; } } // Token: 0x17000633 RID: 1587 // (get) Token: 0x06001325 RID: 4901 RVA: 0x0003A580 File Offset: 0x00038780 public IPEndPoint LocalEndPoint { get { return (IPEndPoint)this.sock.LocalEndPoint; } } // Token: 0x17000634 RID: 1588 // (get) Token: 0x06001326 RID: 4902 RVA: 0x0003A594 File Offset: 0x00038794 public IPEndPoint RemoteEndPoint { get { return (IPEndPoint)this.sock.RemoteEndPoint; } } // Token: 0x17000635 RID: 1589 // (get) Token: 0x06001327 RID: 4903 RVA: 0x0003A5A8 File Offset: 0x000387A8 public bool IsSecure { get { return this.secure; } } // Token: 0x17000636 RID: 1590 // (get) Token: 0x06001328 RID: 4904 RVA: 0x0003A5B0 File Offset: 0x000387B0 // (set) Token: 0x06001329 RID: 4905 RVA: 0x0003A5B8 File Offset: 0x000387B8 public ListenerPrefix Prefix { get { return this.prefix; } set { this.prefix = value; } } // Token: 0x0600132A RID: 4906 RVA: 0x0003A5C4 File Offset: 0x000387C4 public void BeginReadRequest() { if (this.buffer == null) { this.buffer = new byte[8192]; } try { this.stream.BeginRead(this.buffer, 0, 8192, new AsyncCallback(this.OnRead), this); } catch { this.CloseSocket(); } } // Token: 0x0600132B RID: 4907 RVA: 0x0003A640 File Offset: 0x00038840 public RequestStream GetRequestStream(bool chunked, long contentlength) { if (this.i_stream == null) { byte[] array = this.ms.GetBuffer(); int num = (int)this.ms.Length; this.ms = null; if (chunked) { this.chunked = true; this.context.Response.SendChunked = true; this.i_stream = new ChunkedInputStream(this.context, this.stream, array, this.position, num - this.position); } else { this.i_stream = new RequestStream(this.stream, array, this.position, num - this.position, contentlength); } } return this.i_stream; } // Token: 0x0600132C RID: 4908 RVA: 0x0003A6E8 File Offset: 0x000388E8 public ResponseStream GetResponseStream() { if (this.o_stream == null) { HttpListener listener = this.context.Listener; bool flag = listener == null || listener.IgnoreWriteExceptions; this.o_stream = new ResponseStream(this.stream, this.context.Response, flag); } return this.o_stream; } // Token: 0x0600132D RID: 4909 RVA: 0x0003A744 File Offset: 0x00038944 private void OnRead(IAsyncResult ares) { HttpConnection httpConnection = (HttpConnection)ares.AsyncState; int num = -1; try { num = this.stream.EndRead(ares); this.ms.Write(this.buffer, 0, num); if (this.ms.Length > 32768L) { this.SendError("Bad request", 400); this.Close(true); return; } } catch { if (this.ms != null && this.ms.Length > 0L) { this.SendError(); } if (this.sock != null) { this.CloseSocket(); } return; } if (num == 0) { this.CloseSocket(); return; } if (this.ProcessInput(this.ms)) { if (!this.context.HaveError) { this.context.Request.FinishInitialization(); } if (this.context.HaveError) { this.SendError(); this.Close(true); return; } if (!this.epl.BindContext(this.context)) { this.SendError("Invalid host", 400); this.Close(true); } this.context_bound = true; return; } else { this.stream.BeginRead(this.buffer, 0, 8192, new AsyncCallback(this.OnRead), httpConnection); } } // Token: 0x0600132E RID: 4910 RVA: 0x0003A8C8 File Offset: 0x00038AC8 private bool ProcessInput(MemoryStream ms) { byte[] array = ms.GetBuffer(); int num = (int)ms.Length; int num2 = 0; string text; try { text = this.ReadLine(array, this.position, num - this.position, ref num2); this.position += num2; } catch (Exception ex) { this.context.ErrorMessage = "Bad request"; this.context.ErrorStatus = 400; return true; } while (text != null) { if (text == string.Empty) { if (this.input_state != HttpConnection.InputState.RequestLine) { this.current_line = null; ms = null; return true; } } else { if (this.input_state == HttpConnection.InputState.RequestLine) { this.context.Request.SetRequestLine(text); this.input_state = HttpConnection.InputState.Headers; } else { try { this.context.Request.AddHeader(text); } catch (Exception ex2) { this.context.ErrorMessage = ex2.Message; this.context.ErrorStatus = 400; return true; } } if (this.context.HaveError) { return true; } if (this.position >= num) { break; } try { text = this.ReadLine(array, this.position, num - this.position, ref num2); this.position += num2; } catch (Exception ex3) { this.context.ErrorMessage = "Bad request"; this.context.ErrorStatus = 400; return true; } } if (text != null) { continue; } IL_194: if (num2 == num) { ms.SetLength(0L); this.position = 0; } return false; } goto IL_194; } // Token: 0x0600132F RID: 4911 RVA: 0x0003AAD0 File Offset: 0x00038CD0 private string ReadLine(byte[] buffer, int offset, int len, ref int used) { if (this.current_line == null) { this.current_line = new StringBuilder(); } int num = offset + len; used = 0; int num2 = offset; while (num2 < num && this.line_state != HttpConnection.LineState.LF) { used++; byte b = buffer[num2]; if (b == 13) { this.line_state = HttpConnection.LineState.CR; } else if (b == 10) { this.line_state = HttpConnection.LineState.LF; } else { this.current_line.Append((char)b); } num2++; } string text = null; if (this.line_state == HttpConnection.LineState.LF) { this.line_state = HttpConnection.LineState.None; text = this.current_line.ToString(); this.current_line.Length = 0; } return text; } // Token: 0x06001330 RID: 4912 RVA: 0x0003AB8C File Offset: 0x00038D8C public void SendError(string msg, int status) { try { HttpListenerResponse response = this.context.Response; response.StatusCode = status; response.ContentType = "text/html"; string statusDescription = HttpListenerResponse.GetStatusDescription(status); string text; if (msg != null) { text = string.Format("

{0} ({1})

", statusDescription, msg); } else { text = string.Format("

{0}

", statusDescription); } byte[] bytes = this.context.Response.ContentEncoding.GetBytes(text); response.Close(bytes, false); } catch { } } // Token: 0x06001331 RID: 4913 RVA: 0x0003AC28 File Offset: 0x00038E28 public void SendError() { this.SendError(this.context.ErrorMessage, this.context.ErrorStatus); } // Token: 0x06001332 RID: 4914 RVA: 0x0003AC48 File Offset: 0x00038E48 private void Unbind() { if (this.context_bound) { this.epl.UnbindContext(this.context); this.context_bound = false; } } // Token: 0x06001333 RID: 4915 RVA: 0x0003AC70 File Offset: 0x00038E70 public void Close() { this.Close(false); } // Token: 0x06001334 RID: 4916 RVA: 0x0003AC7C File Offset: 0x00038E7C private void CloseSocket() { if (this.sock == null) { return; } try { this.sock.Close(); } catch { } finally { this.sock = null; } } // Token: 0x06001335 RID: 4917 RVA: 0x0003ACE8 File Offset: 0x00038EE8 internal void Close(bool force_close) { if (this.sock != null) { Stream responseStream = this.GetResponseStream(); responseStream.Close(); this.o_stream = null; } if (this.sock == null) { return; } force_close |= this.context.Request.Headers["connection"] == "close"; if (!force_close) { int statusCode = this.context.Response.StatusCode; bool flag = statusCode == 400 || statusCode == 408 || statusCode == 411 || statusCode == 413 || statusCode == 414 || statusCode == 500 || statusCode == 503; force_close |= this.context.Request.ProtocolVersion <= HttpVersion.Version10; } if (force_close || !this.context.Request.FlushInput()) { global::System.Net.Sockets.Socket socket = this.sock; this.sock = null; try { if (socket != null) { socket.Shutdown(global::System.Net.Sockets.SocketShutdown.Both); } } catch { } finally { if (socket != null) { socket.Close(); } } this.Unbind(); return; } if (this.chunked && !this.context.Response.ForceCloseChunked) { this.chunked_uses++; this.Unbind(); this.Init(); this.BeginReadRequest(); return; } this.Unbind(); this.Init(); this.BeginReadRequest(); } // Token: 0x0400104B RID: 4171 private const int BufferSize = 8192; // Token: 0x0400104C RID: 4172 private global::System.Net.Sockets.Socket sock; // Token: 0x0400104D RID: 4173 private Stream stream; // Token: 0x0400104E RID: 4174 private EndPointListener epl; // Token: 0x0400104F RID: 4175 private MemoryStream ms; // Token: 0x04001050 RID: 4176 private byte[] buffer; // Token: 0x04001051 RID: 4177 private HttpListenerContext context; // Token: 0x04001052 RID: 4178 private StringBuilder current_line; // Token: 0x04001053 RID: 4179 private ListenerPrefix prefix; // Token: 0x04001054 RID: 4180 private RequestStream i_stream; // Token: 0x04001055 RID: 4181 private ResponseStream o_stream; // Token: 0x04001056 RID: 4182 private bool chunked; // Token: 0x04001057 RID: 4183 private int chunked_uses; // Token: 0x04001058 RID: 4184 private bool context_bound; // Token: 0x04001059 RID: 4185 private bool secure; // Token: 0x0400105A RID: 4186 private AsymmetricAlgorithm key; // Token: 0x0400105B RID: 4187 private HttpConnection.InputState input_state; // Token: 0x0400105C RID: 4188 private HttpConnection.LineState line_state; // Token: 0x0400105D RID: 4189 private int position; // Token: 0x02000228 RID: 552 private enum InputState { // Token: 0x0400105F RID: 4191 RequestLine, // Token: 0x04001060 RID: 4192 Headers } // Token: 0x02000229 RID: 553 private enum LineState { // Token: 0x04001062 RID: 4194 None, // Token: 0x04001063 RID: 4195 CR, // Token: 0x04001064 RID: 4196 LF } } }