546 lines
12 KiB
C#
546 lines
12 KiB
C#
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("<h1>{0} ({1})</h1>", statusDescription, msg);
|
|
}
|
|
else
|
|
{
|
|
text = string.Format("<h1>{0}</h1>", 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
|
|
}
|
|
}
|
|
}
|