1670 lines
52 KiB
C#
1670 lines
52 KiB
C#
// Decompiled with JetBrains decompiler
|
|
// Type: Rei.Net.HttpServer.MyHttpServerConnection
|
|
// Assembly: Rei.Net.HttpServer, Version=1.13.2.9297, Culture=neutral, PublicKeyToken=null
|
|
// MVID: 6174F8E9-E7BA-46AD-8F2E-196645884F28
|
|
// Assembly location: F:\Eigene Dateien\Dropbox\portable Collection\Progs\CarotDAV\Rei.Net.HttpServer.dll
|
|
|
|
using Microsoft.VisualBasic.CompilerServices;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Specialized;
|
|
using System.Diagnostics;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Text;
|
|
using System.Threading;
|
|
|
|
namespace Rei.Net.HttpServer
|
|
{
|
|
[DebuggerDisplay("{toString}")]
|
|
public class MyHttpServerConnection : IDisposable
|
|
{
|
|
private static string[] HeaderOrder = new string[46]
|
|
{
|
|
"Cache-Control",
|
|
"Connection",
|
|
"Date",
|
|
"Pragma",
|
|
"Trailer",
|
|
"Transfer-Encoding",
|
|
"Upgrade",
|
|
"Via",
|
|
"Warning",
|
|
"Accept-Charset",
|
|
"Accept-Encoding",
|
|
"Accept-Language",
|
|
"Authorization",
|
|
"Expect",
|
|
"From",
|
|
"Host",
|
|
"If-Match",
|
|
"If-Modified-Since",
|
|
"If-None-Match",
|
|
"If-Range",
|
|
"If-Unmodified-Since",
|
|
"Max-Forwards",
|
|
"Proxy-Authorization",
|
|
"Range",
|
|
"Referer",
|
|
"TE",
|
|
"User-Agent",
|
|
"Accept-Ranges",
|
|
"Age",
|
|
"ETag",
|
|
"Location",
|
|
"Proxy-Authenticate",
|
|
"Retry-After",
|
|
"Server",
|
|
"Vary",
|
|
"WWW-Authenticate",
|
|
"Allow",
|
|
"Content-Encoding",
|
|
"Content-Language",
|
|
"Content-Length",
|
|
"Content-Location",
|
|
"Content-MD5",
|
|
"Content-Range",
|
|
"Content-Type",
|
|
"Expires",
|
|
"Last-Modified"
|
|
};
|
|
private object _Tag;
|
|
private object _syncobject;
|
|
private LineReadableSocketStream _st;
|
|
private bool _needclose;
|
|
private bool _isconnected;
|
|
private MyEndPoint _remoteep;
|
|
private int _requesttimeout;
|
|
private int _responsetimeout;
|
|
private MyHttpServerConnection.StreamStateType _req_state;
|
|
private bool _req_closed;
|
|
private string _req_method;
|
|
private MyHttpServerConnection.BodyLengthType _req_bodylengthtype;
|
|
private long _req_contentlength;
|
|
private string _req_currentheader;
|
|
private long _req_currentposition;
|
|
private int _req_currentchunksize;
|
|
private bool _req_expect100continue;
|
|
private MyHttpServerConnection.StreamStateType _res_state;
|
|
private bool _res_closed;
|
|
private MyHttpServerConnection.BodyLengthType _res_bodylengthtype;
|
|
private long _res_contentlength;
|
|
private bool _res_sentexpect100continue;
|
|
private long _res_currentposition;
|
|
private string _res_headers;
|
|
private bool disposedValue;
|
|
|
|
public MyHttpServerConnection(Socket basesocket)
|
|
{
|
|
this.disposedValue = false;
|
|
this._syncobject = RuntimeHelpers.GetObjectValue(new object());
|
|
this._remoteep = new MyEndPoint((IPEndPoint) basesocket.RemoteEndPoint);
|
|
this._st = new LineReadableSocketStream(basesocket);
|
|
this._needclose = false;
|
|
this._isconnected = true;
|
|
this._requesttimeout = 300000;
|
|
this._responsetimeout = 300000;
|
|
this._req_state = MyHttpServerConnection.StreamStateType.Initial;
|
|
this._req_closed = false;
|
|
this._res_state = MyHttpServerConnection.StreamStateType.Initial;
|
|
this._res_closed = false;
|
|
}
|
|
|
|
public LineReadableSocketStream BaseStream
|
|
{
|
|
get
|
|
{
|
|
return this._st;
|
|
}
|
|
set
|
|
{
|
|
this._st = value;
|
|
}
|
|
}
|
|
|
|
public int ReadTimeout
|
|
{
|
|
get
|
|
{
|
|
return this._st.ReadTimeout;
|
|
}
|
|
set
|
|
{
|
|
this._st.ReadTimeout = value;
|
|
}
|
|
}
|
|
|
|
public int WriteTimeout
|
|
{
|
|
get
|
|
{
|
|
return this._st.WriteTimeout;
|
|
}
|
|
set
|
|
{
|
|
this._st.WriteTimeout = value;
|
|
}
|
|
}
|
|
|
|
public int RequestTimeout
|
|
{
|
|
get
|
|
{
|
|
return this._requesttimeout;
|
|
}
|
|
set
|
|
{
|
|
this._requesttimeout = value;
|
|
}
|
|
}
|
|
|
|
public int ResponseTimeout
|
|
{
|
|
get
|
|
{
|
|
return this._responsetimeout;
|
|
}
|
|
set
|
|
{
|
|
this._responsetimeout = value;
|
|
}
|
|
}
|
|
|
|
public bool IsConnected
|
|
{
|
|
get
|
|
{
|
|
return this._isconnected;
|
|
}
|
|
}
|
|
|
|
public MyEndPoint RemoteEp
|
|
{
|
|
get
|
|
{
|
|
return this._remoteep;
|
|
}
|
|
}
|
|
|
|
public object Tag
|
|
{
|
|
get
|
|
{
|
|
return this._Tag;
|
|
}
|
|
set
|
|
{
|
|
this._Tag = RuntimeHelpers.GetObjectValue(value);
|
|
}
|
|
}
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (!this.disposedValue && disposing && this._st != null)
|
|
{
|
|
this._st.Close();
|
|
this._st = (LineReadableSocketStream) null;
|
|
}
|
|
this.disposedValue = true;
|
|
}
|
|
|
|
public void Close()
|
|
{
|
|
this.Dispose(true);
|
|
GC.SuppressFinalize((object) this);
|
|
}
|
|
|
|
public MyHttpServerRequest ReceiveRequest()
|
|
{
|
|
return this.ReceiveRequest(this.RequestTimeout);
|
|
}
|
|
|
|
public MyHttpServerRequest ReceiveRequest(int timeout)
|
|
{
|
|
IAsyncResult request = this.BeginReceiveRequest((AsyncCallback) null, (object) null);
|
|
if (!request.CompletedSynchronously && !request.AsyncWaitHandle.WaitOne(timeout, false))
|
|
throw new IOException("Timeout");
|
|
return this.EndReceiveRequest(request);
|
|
}
|
|
|
|
public IAsyncResult BeginReceiveRequest(AsyncCallback callback, object asyncstate)
|
|
{
|
|
object syncobject = this._syncobject;
|
|
ObjectFlowControl.CheckForSyncLockOnValueType(syncobject);
|
|
Monitor.Enter(syncobject);
|
|
try
|
|
{
|
|
if (this._req_state != MyHttpServerConnection.StreamStateType.Initial)
|
|
throw new InvalidOperationException();
|
|
this._req_state = MyHttpServerConnection.StreamStateType.Changing;
|
|
}
|
|
finally
|
|
{
|
|
Monitor.Exit(syncobject);
|
|
}
|
|
MyAsyncResult myAsyncResult = new MyAsyncResult(callback, RuntimeHelpers.GetObjectValue(asyncstate));
|
|
this._st.BeginReadLine(new AsyncCallback(this.OnRead_RequestLine), (object) myAsyncResult);
|
|
return (IAsyncResult) myAsyncResult;
|
|
}
|
|
|
|
private void OnRead_RequestLine(IAsyncResult asyncresult)
|
|
{
|
|
MyAsyncResult asyncState = (MyAsyncResult) asyncresult.AsyncState;
|
|
MyHttpServerRequest req = new MyHttpServerRequest();
|
|
asyncState.ReturnValue = (object) req;
|
|
if (!asyncresult.CompletedSynchronously)
|
|
asyncState.SetAsync();
|
|
try
|
|
{
|
|
req._requestline = this._st.EndReadLine(asyncresult);
|
|
if (req._requestline == null)
|
|
asyncState.Complete();
|
|
else if (Operators.CompareString(req._requestline, "", false) == 0)
|
|
{
|
|
this._st.BeginReadLine(new AsyncCallback(this.OnRead_RequestLine), (object) asyncState);
|
|
}
|
|
else
|
|
{
|
|
string[] strArray = req._requestline.Split(new char[1]
|
|
{
|
|
' '
|
|
}, 3, StringSplitOptions.RemoveEmptyEntries);
|
|
if (strArray.Length < 2)
|
|
{
|
|
this.RequestStreamClose();
|
|
throw new MyHttpServerBadRequestException(req);
|
|
}
|
|
if (strArray[2].Length != 8)
|
|
{
|
|
this.RequestStreamClose();
|
|
throw new MyHttpServerBadRequestException(req);
|
|
}
|
|
if (string.Compare(strArray[2].Substring(0, 5), "HTTP/", StringComparison.InvariantCultureIgnoreCase) != 0)
|
|
{
|
|
this.RequestStreamClose();
|
|
throw new MyHttpServerBadRequestException(req);
|
|
}
|
|
float.Parse(strArray[2].Substring(5, 3));
|
|
req._method = strArray[0];
|
|
req._rawuri = strArray[1];
|
|
req._version = strArray[2];
|
|
this._req_method = req._method;
|
|
this._req_currentheader = (string) null;
|
|
this._st.BeginReadLine(new AsyncCallback(this.OnRead_Header), RuntimeHelpers.GetObjectValue(asyncresult.AsyncState));
|
|
}
|
|
}
|
|
catch (Exception ex1)
|
|
{
|
|
ProjectData.SetProjectError(ex1);
|
|
Exception ex2 = ex1;
|
|
asyncState.Complete(ex2);
|
|
ProjectData.ClearProjectError();
|
|
}
|
|
}
|
|
|
|
private void OnRead_Header(IAsyncResult asyncresult)
|
|
{
|
|
MyAsyncResult asyncState = (MyAsyncResult) asyncresult.AsyncState;
|
|
MyHttpServerRequest returnValue = (MyHttpServerRequest) asyncState.ReturnValue;
|
|
if (!asyncresult.CompletedSynchronously)
|
|
asyncState.SetAsync();
|
|
try
|
|
{
|
|
string Left = this._st.EndReadLine(asyncresult);
|
|
if (Left == null)
|
|
throw new MyHttpServerConnectionClosedException("Client Closed");
|
|
if (this._req_currentheader == null)
|
|
{
|
|
this._req_currentheader = Left;
|
|
this._st.BeginReadLine(new AsyncCallback(this.OnRead_Header), RuntimeHelpers.GetObjectValue(asyncresult.AsyncState));
|
|
return;
|
|
}
|
|
if (Left.Length > 0 && (Operators.CompareString(Conversions.ToString(Left[0]), " ", false) == 0 || Operators.CompareString(Conversions.ToString(Left[0]), "\t", false) == 0))
|
|
{
|
|
this._req_currentheader = this._req_currentheader + Left;
|
|
this._st.BeginReadLine(new AsyncCallback(this.OnRead_Header), RuntimeHelpers.GetObjectValue(asyncresult.AsyncState));
|
|
return;
|
|
}
|
|
int length = this._req_currentheader.IndexOf(":");
|
|
if (length < 0)
|
|
{
|
|
returnValue._requestheaders.Add(this._req_currentheader, "");
|
|
}
|
|
else
|
|
{
|
|
string name = this._req_currentheader.Substring(0, length).Trim();
|
|
string str = this._req_currentheader.Substring(checked (length + 1)).Trim();
|
|
returnValue._requestheaders.Add(name, str);
|
|
}
|
|
if (Operators.CompareString(Left, "", false) != 0)
|
|
{
|
|
this._req_currentheader = Left;
|
|
this._st.BeginReadLine(new AsyncCallback(this.OnRead_Header), RuntimeHelpers.GetObjectValue(asyncresult.AsyncState));
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex1)
|
|
{
|
|
ProjectData.SetProjectError(ex1);
|
|
Exception ex2 = ex1;
|
|
asyncState.Complete(ex2);
|
|
ProjectData.ClearProjectError();
|
|
return;
|
|
}
|
|
asyncState.Complete();
|
|
}
|
|
|
|
public MyHttpServerRequest EndReceiveRequest(IAsyncResult asyncresult)
|
|
{
|
|
MyAsyncResult myAsyncResult = (MyAsyncResult) asyncresult;
|
|
myAsyncResult.AsyncEnd();
|
|
MyHttpServerRequest returnValue = (MyHttpServerRequest) myAsyncResult.ReturnValue;
|
|
if (returnValue._requestline == null)
|
|
return (MyHttpServerRequest) null;
|
|
string requestheader1 = returnValue._requestheaders["Content-Length"];
|
|
if (requestheader1 != null)
|
|
{
|
|
if (!long.TryParse(requestheader1, out returnValue._contentlength))
|
|
returnValue._contentlength = 0L;
|
|
}
|
|
else
|
|
returnValue._contentlength = 0L;
|
|
this._req_contentlength = returnValue._contentlength;
|
|
string requestheader2 = returnValue._requestheaders["Transfer-Encoding"];
|
|
bool flag;
|
|
if (requestheader2 != null)
|
|
{
|
|
if (string.Compare(requestheader2.Trim(), "chunked", StringComparison.InvariantCultureIgnoreCase) != 0)
|
|
{
|
|
this.RequestStreamClose();
|
|
throw new MyHttpServerBadRequestException(returnValue);
|
|
}
|
|
flag = true;
|
|
}
|
|
else
|
|
flag = false;
|
|
string[] values1 = returnValue._requestheaders.GetValues("Connection");
|
|
if (values1 != null)
|
|
{
|
|
int num1 = 0;
|
|
int num2 = checked (values1.Length - 1);
|
|
int index = num1;
|
|
while (index <= num2)
|
|
{
|
|
if (string.Compare(values1[index], "Close", StringComparison.InvariantCultureIgnoreCase) == 0)
|
|
this._needclose = true;
|
|
checked { ++index; }
|
|
}
|
|
}
|
|
string[] values2 = returnValue._requestheaders.GetValues("Expect");
|
|
returnValue._expect100continue = false;
|
|
if (values2 != null)
|
|
{
|
|
int num1 = 0;
|
|
int num2 = checked (values2.Length - 1);
|
|
int index = num1;
|
|
while (index <= num2)
|
|
{
|
|
if (string.Compare(values2[index], "100-continue", StringComparison.InvariantCultureIgnoreCase) == 0)
|
|
returnValue._expect100continue = true;
|
|
checked { ++index; }
|
|
}
|
|
}
|
|
this._req_expect100continue = returnValue._expect100continue;
|
|
this._res_sentexpect100continue = false;
|
|
returnValue._host = returnValue._requestheaders["Host"];
|
|
if (returnValue._host == null)
|
|
{
|
|
this.RequestStreamClose();
|
|
throw new MyHttpServerBadRequestException(returnValue);
|
|
}
|
|
if (Operators.CompareString(returnValue._rawuri, "*", false) != 0 && !returnValue._rawuri.StartsWith("http://"))
|
|
{
|
|
if (returnValue._rawuri.StartsWith("/"))
|
|
{
|
|
if (!Uri.TryCreate("http://" + returnValue._host + returnValue._rawuri, UriKind.Absolute, out returnValue._requesturi))
|
|
throw new MyHttpServerBadRequestException(returnValue);
|
|
}
|
|
else
|
|
{
|
|
if (Operators.CompareString(returnValue.Method.ToUpperInvariant(), "CONNECT", false) != 0)
|
|
throw new MyHttpServerBadRequestException(returnValue);
|
|
if (!Uri.TryCreate("http://" + returnValue._rawuri, UriKind.Absolute, out returnValue._requesturi))
|
|
throw new MyHttpServerBadRequestException(returnValue);
|
|
if (returnValue._requesturi.Segments.Length != 1)
|
|
{
|
|
this.RequestStreamClose();
|
|
throw new MyHttpServerBadRequestException(returnValue);
|
|
}
|
|
}
|
|
}
|
|
if (flag)
|
|
this._req_bodylengthtype = MyHttpServerConnection.BodyLengthType.Chunk;
|
|
else if (returnValue._contentlength >= 0L)
|
|
{
|
|
this._req_bodylengthtype = MyHttpServerConnection.BodyLengthType.ContentLength;
|
|
}
|
|
else
|
|
{
|
|
this.RequestStreamClose();
|
|
throw new MyHttpServerBadRequestException(returnValue);
|
|
}
|
|
returnValue._reqstream = (Stream) new MyHttpServerConnection.RequestStream(this);
|
|
object syncobject = this._syncobject;
|
|
ObjectFlowControl.CheckForSyncLockOnValueType(syncobject);
|
|
Monitor.Enter(syncobject);
|
|
try
|
|
{
|
|
this._req_state = MyHttpServerConnection.StreamStateType.HeaderFinished;
|
|
if (returnValue._contentlength == 0L)
|
|
this._req_state = MyHttpServerConnection.StreamStateType.BodyFinished;
|
|
}
|
|
finally
|
|
{
|
|
Monitor.Exit(syncobject);
|
|
}
|
|
return returnValue;
|
|
}
|
|
|
|
private long RequestStreamLength()
|
|
{
|
|
object syncobject = this._syncobject;
|
|
ObjectFlowControl.CheckForSyncLockOnValueType(syncobject);
|
|
Monitor.Enter(syncobject);
|
|
try
|
|
{
|
|
if (this._req_state < MyHttpServerConnection.StreamStateType.HeaderFinished)
|
|
throw new InvalidOperationException();
|
|
}
|
|
finally
|
|
{
|
|
Monitor.Exit(syncobject);
|
|
}
|
|
return this._req_contentlength;
|
|
}
|
|
|
|
private long RequestStreamPosition()
|
|
{
|
|
return this._req_currentposition;
|
|
}
|
|
|
|
private IAsyncResult RequestStreamBeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
|
|
{
|
|
if (count < 0)
|
|
throw new ArgumentOutOfRangeException();
|
|
object syncobject = this._syncobject;
|
|
ObjectFlowControl.CheckForSyncLockOnValueType(syncobject);
|
|
Monitor.Enter(syncobject);
|
|
bool flag;
|
|
try
|
|
{
|
|
flag = this._req_state == MyHttpServerConnection.StreamStateType.BodyFinished;
|
|
if (!flag)
|
|
{
|
|
if (this._req_state != MyHttpServerConnection.StreamStateType.HeaderFinished)
|
|
throw new InvalidOperationException();
|
|
this._req_state = MyHttpServerConnection.StreamStateType.Changing;
|
|
}
|
|
if (this._req_expect100continue)
|
|
{
|
|
if (!this._res_sentexpect100continue)
|
|
{
|
|
if (!flag)
|
|
{
|
|
if (this._res_state != MyHttpServerConnection.StreamStateType.Initial)
|
|
throw new InvalidOperationException();
|
|
this._res_state = MyHttpServerConnection.StreamStateType.Changing;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
Monitor.Exit(syncobject);
|
|
}
|
|
MyAsyncResult mar = new MyAsyncResult(callback, RuntimeHelpers.GetObjectValue(state));
|
|
if (flag)
|
|
{
|
|
mar.ReturnValue = (object) 0;
|
|
mar.Complete();
|
|
return (IAsyncResult) mar;
|
|
}
|
|
mar.Tag = (object) new MyHttpServerConnection.StreamReadWriteParameter()
|
|
{
|
|
buffer = buffer,
|
|
offset = offset,
|
|
count = count
|
|
};
|
|
if (this._req_expect100continue && !this._res_sentexpect100continue)
|
|
{
|
|
byte[] bytes = Encoding.UTF8.GetBytes("HTTP/1.1 100 Continue\r\n\r\n");
|
|
this._st.BeginWrite(bytes, 0, bytes.Length, new AsyncCallback(this.OnRead_SendExpect100Continue), (object) mar);
|
|
}
|
|
else
|
|
this.InnerRequestStreamBeginRead2(mar);
|
|
return (IAsyncResult) mar;
|
|
}
|
|
|
|
private void OnRead_SendExpect100Continue(IAsyncResult asyncresult)
|
|
{
|
|
MyAsyncResult asyncState = (MyAsyncResult) asyncresult.AsyncState;
|
|
MyHttpServerConnection.StreamReadWriteParameter tag = (MyHttpServerConnection.StreamReadWriteParameter) asyncState.Tag;
|
|
if (!asyncresult.CompletedSynchronously)
|
|
asyncState.SetAsync();
|
|
try
|
|
{
|
|
this._st.EndWrite(asyncresult);
|
|
this._res_sentexpect100continue = true;
|
|
object syncobject = this._syncobject;
|
|
ObjectFlowControl.CheckForSyncLockOnValueType(syncobject);
|
|
Monitor.Enter(syncobject);
|
|
try
|
|
{
|
|
this._res_state = MyHttpServerConnection.StreamStateType.Initial;
|
|
}
|
|
finally
|
|
{
|
|
Monitor.Exit(syncobject);
|
|
}
|
|
this.InnerRequestStreamBeginRead2(asyncState);
|
|
}
|
|
catch (Exception ex1)
|
|
{
|
|
ProjectData.SetProjectError(ex1);
|
|
Exception ex2 = ex1;
|
|
asyncState.Complete(ex2);
|
|
ProjectData.ClearProjectError();
|
|
}
|
|
}
|
|
|
|
private void InnerRequestStreamBeginRead2(MyAsyncResult mar)
|
|
{
|
|
MyHttpServerConnection.StreamReadWriteParameter tag = (MyHttpServerConnection.StreamReadWriteParameter) mar.Tag;
|
|
switch (this._req_bodylengthtype)
|
|
{
|
|
case MyHttpServerConnection.BodyLengthType.Chunk:
|
|
if (this._req_currentchunksize == 0)
|
|
{
|
|
this._st.BeginReadLine(new AsyncCallback(this.OnRead_Body_ChunkSize), (object) mar);
|
|
break;
|
|
}
|
|
int count1 = tag.count;
|
|
if (count1 > this._req_currentchunksize)
|
|
count1 = this._req_currentchunksize;
|
|
this._st.BeginRead(tag.buffer, tag.offset, count1, new AsyncCallback(this.OnRead_Body_ChunkData), (object) mar);
|
|
break;
|
|
case MyHttpServerConnection.BodyLengthType.ContentLength:
|
|
int count2 = tag.count;
|
|
if (checked (this._req_currentposition + (long) count2) > this._req_contentlength)
|
|
count2 = checked ((int) (this._req_contentlength - this._req_currentposition));
|
|
this._st.BeginRead(tag.buffer, tag.offset, count2, new AsyncCallback(this.OnRead_Body_ContentLength), (object) mar);
|
|
break;
|
|
default:
|
|
this.RequestStreamClose();
|
|
throw new MyHttpServerBadRequestException((MyHttpServerRequest) null);
|
|
}
|
|
}
|
|
|
|
private void OnRead_Body_ContentLength(IAsyncResult asyncresult)
|
|
{
|
|
MyAsyncResult asyncState = (MyAsyncResult) asyncresult.AsyncState;
|
|
if (!asyncresult.CompletedSynchronously)
|
|
asyncState.SetAsync();
|
|
try
|
|
{
|
|
int num = this._st.EndRead(asyncresult);
|
|
if (num == 0)
|
|
throw new MyHttpServerConnectionClosedException("Client Closed");
|
|
this._req_currentposition = checked (this._req_currentposition + (long) num);
|
|
asyncState.ReturnValue = (object) num;
|
|
}
|
|
catch (Exception ex1)
|
|
{
|
|
ProjectData.SetProjectError(ex1);
|
|
Exception ex2 = ex1;
|
|
asyncState.Complete(ex2);
|
|
ProjectData.ClearProjectError();
|
|
return;
|
|
}
|
|
asyncState.Complete();
|
|
}
|
|
|
|
private void OnRead_Body_ChunkSize(IAsyncResult asyncresult)
|
|
{
|
|
MyAsyncResult asyncState = (MyAsyncResult) asyncresult.AsyncState;
|
|
MyHttpServerConnection.StreamReadWriteParameter tag = (MyHttpServerConnection.StreamReadWriteParameter) asyncState.Tag;
|
|
if (!asyncresult.CompletedSynchronously)
|
|
asyncState.SetAsync();
|
|
try
|
|
{
|
|
string str = this._st.EndReadLine(asyncresult);
|
|
if (str == null)
|
|
throw new MyHttpServerConnectionClosedException("Client Closed");
|
|
int length = str.IndexOf(";");
|
|
if (length >= 0)
|
|
str = str.Substring(0, length);
|
|
if (!int.TryParse(str.Trim(), NumberStyles.AllowHexSpecifier, (IFormatProvider) null, out this._req_currentchunksize))
|
|
{
|
|
this.RequestStreamClose();
|
|
throw new MyHttpServerBadRequestException((MyHttpServerRequest) null);
|
|
}
|
|
if (this._req_currentchunksize == 0)
|
|
{
|
|
this._st.BeginReadLine(new AsyncCallback(this.OnRead_Body_ChunkTrailer), (object) asyncState);
|
|
}
|
|
else
|
|
{
|
|
int count = tag.count;
|
|
if (count > this._req_currentchunksize)
|
|
count = this._req_currentchunksize;
|
|
this._st.BeginRead(tag.buffer, tag.offset, count, new AsyncCallback(this.OnRead_Body_ChunkData), (object) asyncState);
|
|
}
|
|
}
|
|
catch (Exception ex1)
|
|
{
|
|
ProjectData.SetProjectError(ex1);
|
|
Exception ex2 = ex1;
|
|
asyncState.Complete(ex2);
|
|
ProjectData.ClearProjectError();
|
|
}
|
|
}
|
|
|
|
private void OnRead_Body_ChunkData(IAsyncResult asyncresult)
|
|
{
|
|
MyAsyncResult asyncState = (MyAsyncResult) asyncresult.AsyncState;
|
|
if (!asyncresult.CompletedSynchronously)
|
|
asyncState.SetAsync();
|
|
try
|
|
{
|
|
int num = this._st.EndRead(asyncresult);
|
|
if (num == 0)
|
|
{
|
|
this.RequestStreamClose();
|
|
throw new MyHttpServerBadRequestException((MyHttpServerRequest) null);
|
|
}
|
|
this._req_currentchunksize = checked (this._req_currentchunksize - num);
|
|
this._req_currentposition = checked (this._req_currentposition + (long) num);
|
|
asyncState.ReturnValue = (object) num;
|
|
this._st.BeginReadLine(new AsyncCallback(this.OnRead_Body_ChunkDataEnd), (object) asyncState);
|
|
}
|
|
catch (Exception ex1)
|
|
{
|
|
ProjectData.SetProjectError(ex1);
|
|
Exception ex2 = ex1;
|
|
asyncState.Complete(ex2);
|
|
ProjectData.ClearProjectError();
|
|
}
|
|
}
|
|
|
|
private void OnRead_Body_ChunkDataEnd(IAsyncResult asyncresult)
|
|
{
|
|
MyAsyncResult asyncState = (MyAsyncResult) asyncresult.AsyncState;
|
|
if (!asyncresult.CompletedSynchronously)
|
|
asyncState.SetAsync();
|
|
try
|
|
{
|
|
this._st.EndReadLine((IAsyncResult) asyncState);
|
|
}
|
|
catch (Exception ex1)
|
|
{
|
|
ProjectData.SetProjectError(ex1);
|
|
Exception ex2 = ex1;
|
|
asyncState.Complete(ex2);
|
|
ProjectData.ClearProjectError();
|
|
return;
|
|
}
|
|
asyncState.Complete();
|
|
}
|
|
|
|
private void OnRead_Body_ChunkTrailer(IAsyncResult asyncresult)
|
|
{
|
|
MyAsyncResult asyncState = (MyAsyncResult) asyncresult.AsyncState;
|
|
if (!asyncresult.CompletedSynchronously)
|
|
asyncState.SetAsync();
|
|
try
|
|
{
|
|
if (this._st.EndReadLine((IAsyncResult) asyncState).Length == 0)
|
|
{
|
|
object syncobject = this._syncobject;
|
|
ObjectFlowControl.CheckForSyncLockOnValueType(syncobject);
|
|
Monitor.Enter(syncobject);
|
|
try
|
|
{
|
|
this._req_state = MyHttpServerConnection.StreamStateType.BodyFinished;
|
|
}
|
|
finally
|
|
{
|
|
Monitor.Exit(syncobject);
|
|
}
|
|
asyncState.ReturnValue = (object) 0;
|
|
asyncState.Complete();
|
|
}
|
|
else
|
|
this._st.BeginReadLine(new AsyncCallback(this.OnRead_Body_ChunkTrailer), (object) asyncState);
|
|
}
|
|
catch (Exception ex1)
|
|
{
|
|
ProjectData.SetProjectError(ex1);
|
|
Exception ex2 = ex1;
|
|
asyncState.Complete(ex2);
|
|
ProjectData.ClearProjectError();
|
|
return;
|
|
}
|
|
asyncState.Complete();
|
|
}
|
|
|
|
private int RequestStreamEndRead(IAsyncResult asyncResult)
|
|
{
|
|
MyAsyncResult myAsyncResult = (MyAsyncResult) asyncResult;
|
|
myAsyncResult.AsyncEnd();
|
|
int returnValue = (int) myAsyncResult.ReturnValue;
|
|
if (returnValue == 0 && this._req_state != MyHttpServerConnection.StreamStateType.BodyFinished)
|
|
throw new MyHttpServerBadRequestException((MyHttpServerRequest) null);
|
|
object syncobject = this._syncobject;
|
|
ObjectFlowControl.CheckForSyncLockOnValueType(syncobject);
|
|
Monitor.Enter(syncobject);
|
|
try
|
|
{
|
|
this._req_state = MyHttpServerConnection.StreamStateType.HeaderFinished;
|
|
if (this._req_currentposition >= this._req_contentlength)
|
|
this._req_state = MyHttpServerConnection.StreamStateType.BodyFinished;
|
|
}
|
|
finally
|
|
{
|
|
Monitor.Exit(syncobject);
|
|
}
|
|
return returnValue;
|
|
}
|
|
|
|
public Stream SendResponse(MyHttpServerResponse response)
|
|
{
|
|
return this.SendResponse(response, this.ResponseTimeout);
|
|
}
|
|
|
|
public Stream SendResponse(MyHttpServerResponse response, int timeout)
|
|
{
|
|
IAsyncResult asyncresult = this.BeginSendResponse(response, (AsyncCallback) null, (object) null);
|
|
if (!asyncresult.CompletedSynchronously && !asyncresult.AsyncWaitHandle.WaitOne(timeout, false))
|
|
throw new IOException("Timeout");
|
|
return this.EndSendResponse(asyncresult);
|
|
}
|
|
|
|
public IAsyncResult BeginSendResponse(MyHttpServerResponse response, AsyncCallback callback, object asyncstate)
|
|
{
|
|
object syncobject = this._syncobject;
|
|
ObjectFlowControl.CheckForSyncLockOnValueType(syncobject);
|
|
Monitor.Enter(syncobject);
|
|
try
|
|
{
|
|
if (this._res_state != MyHttpServerConnection.StreamStateType.Initial)
|
|
throw new InvalidOperationException();
|
|
this._res_state = MyHttpServerConnection.StreamStateType.Changing;
|
|
}
|
|
finally
|
|
{
|
|
Monitor.Exit(syncobject);
|
|
}
|
|
MyAsyncResult myAsyncResult = new MyAsyncResult(callback, RuntimeHelpers.GetObjectValue(asyncstate));
|
|
NameValueCollection nameValueCollection = new NameValueCollection(response._responseheaders);
|
|
if (Operators.CompareString(this._req_method, "HEAD", false) == 0)
|
|
{
|
|
this._res_bodylengthtype = MyHttpServerConnection.BodyLengthType.NoBody;
|
|
this._res_contentlength = response._contentlength;
|
|
}
|
|
else if (response._statuscode == 204 || response._statuscode == 304)
|
|
{
|
|
this._res_bodylengthtype = MyHttpServerConnection.BodyLengthType.ContentLength;
|
|
this._res_contentlength = 0L;
|
|
}
|
|
else if (response._sendchunked)
|
|
{
|
|
this._res_bodylengthtype = MyHttpServerConnection.BodyLengthType.Chunk;
|
|
this._res_contentlength = -1L;
|
|
}
|
|
else
|
|
{
|
|
if (response._contentlength < 0L)
|
|
throw new Exception();
|
|
this._res_bodylengthtype = MyHttpServerConnection.BodyLengthType.ContentLength;
|
|
this._res_contentlength = response._contentlength;
|
|
}
|
|
if (string.IsNullOrEmpty(response._statusdesc))
|
|
{
|
|
switch (response.StatusCode)
|
|
{
|
|
case 200:
|
|
response._statusdesc = "OK";
|
|
break;
|
|
case 201:
|
|
response._statusdesc = "Created";
|
|
break;
|
|
case 202:
|
|
response._statusdesc = "Accepted";
|
|
break;
|
|
case 203:
|
|
response._statusdesc = "Non-Authoritative Information";
|
|
break;
|
|
case 204:
|
|
response._statusdesc = "No Content";
|
|
break;
|
|
case 205:
|
|
response._statusdesc = "Reset Content";
|
|
break;
|
|
case 206:
|
|
response._statusdesc = "Partial Content";
|
|
break;
|
|
case 207:
|
|
response._statusdesc = "Multi-Status";
|
|
break;
|
|
case 300:
|
|
response._statusdesc = "Multiple Choices";
|
|
break;
|
|
case 301:
|
|
response._statusdesc = "Moved Permanently";
|
|
break;
|
|
case 302:
|
|
response._statusdesc = "Found";
|
|
break;
|
|
case 303:
|
|
response._statusdesc = "See Other";
|
|
break;
|
|
case 304:
|
|
response._statusdesc = "Not Modified";
|
|
break;
|
|
case 305:
|
|
response._statusdesc = "Use Proxy";
|
|
break;
|
|
case 306:
|
|
response._statusdesc = "(Unused)";
|
|
break;
|
|
case 307:
|
|
response._statusdesc = "Temporary Redirect";
|
|
break;
|
|
case 400:
|
|
response._statusdesc = "Bad Request";
|
|
break;
|
|
case 401:
|
|
response._statusdesc = "Unauthorized";
|
|
break;
|
|
case 402:
|
|
response._statusdesc = "Payment Required";
|
|
break;
|
|
case 403:
|
|
response._statusdesc = "Forbidden";
|
|
break;
|
|
case 404:
|
|
response._statusdesc = "Not Found";
|
|
break;
|
|
case 405:
|
|
response._statusdesc = "Method Not Allowed";
|
|
break;
|
|
case 406:
|
|
response._statusdesc = "Not Acceptable";
|
|
break;
|
|
case 407:
|
|
response._statusdesc = "Proxy Authentication Required";
|
|
break;
|
|
case 408:
|
|
response._statusdesc = "Request Timeout";
|
|
break;
|
|
case 409:
|
|
response._statusdesc = "Conflict";
|
|
break;
|
|
case 410:
|
|
response._statusdesc = "Gone";
|
|
break;
|
|
case 411:
|
|
response._statusdesc = "Length Required";
|
|
break;
|
|
case 412:
|
|
response._statusdesc = "Precondition Failed";
|
|
break;
|
|
case 413:
|
|
response._statusdesc = "Request Entity Too Large";
|
|
break;
|
|
case 414:
|
|
response._statusdesc = "Request-URI Too Long";
|
|
break;
|
|
case 415:
|
|
response._statusdesc = "Unsupported Media Type";
|
|
break;
|
|
case 416:
|
|
response._statusdesc = "Requested Range Not Satisfiable";
|
|
break;
|
|
case 417:
|
|
response._statusdesc = "Expectation Failed";
|
|
break;
|
|
case 422:
|
|
response._statusdesc = "Unprocessable Entity";
|
|
break;
|
|
case 423:
|
|
response._statusdesc = "Locked";
|
|
break;
|
|
case 424:
|
|
response._statusdesc = "Failed Dependency";
|
|
break;
|
|
case 500:
|
|
response._statusdesc = "Internal Server Error";
|
|
break;
|
|
case 501:
|
|
response._statusdesc = "Not Implemented";
|
|
break;
|
|
case 502:
|
|
response._statusdesc = "Bad Gateway";
|
|
break;
|
|
case 503:
|
|
response._statusdesc = "Service Unavailable";
|
|
break;
|
|
case 504:
|
|
response._statusdesc = "Gateway Timeout";
|
|
break;
|
|
case 505:
|
|
response._statusdesc = "HTTP Version Not Supported";
|
|
break;
|
|
case 506:
|
|
response._statusdesc = "Variant Also Negotiates";
|
|
break;
|
|
case 507:
|
|
response._statusdesc = "Insufficient Storage";
|
|
break;
|
|
default:
|
|
response._statusdesc = "";
|
|
break;
|
|
}
|
|
}
|
|
string str1 = string.Join(" ", new string[3]
|
|
{
|
|
"HTTP/1.1",
|
|
response._statuscode.ToString(),
|
|
response._statusdesc
|
|
});
|
|
if (this._needclose)
|
|
nameValueCollection.Add("Connection", "Close");
|
|
string[] values1 = nameValueCollection.GetValues("Connection");
|
|
if (values1 != null)
|
|
{
|
|
int num1 = 0;
|
|
int num2 = checked (values1.Length - 1);
|
|
int index = num1;
|
|
while (index <= num2)
|
|
{
|
|
if (string.Compare(values1[index], "Close", StringComparison.InvariantCultureIgnoreCase) == 0)
|
|
this._needclose = true;
|
|
checked { ++index; }
|
|
}
|
|
}
|
|
if (nameValueCollection["Transfer-Encoding"] != null && Operators.CompareString(nameValueCollection["Transfer-Encoding"], "chunked", false) != 0)
|
|
throw new NotImplementedException();
|
|
if (response._sendchunked)
|
|
nameValueCollection["Transfer-Encoding"] = "chunked";
|
|
if (nameValueCollection["Date"] == null)
|
|
nameValueCollection.Add("Date", DateTime.Now.ToUniversalTime().ToString("r"));
|
|
if (this._res_bodylengthtype == MyHttpServerConnection.BodyLengthType.Chunk)
|
|
nameValueCollection.Remove("Content-Length");
|
|
else
|
|
nameValueCollection["Content-Length"] = this._res_contentlength.ToString();
|
|
List<string> stringList = new List<string>();
|
|
stringList.Add(str1);
|
|
string[] headerOrder = MyHttpServerConnection.HeaderOrder;
|
|
int index1 = 0;
|
|
while (index1 < headerOrder.Length)
|
|
{
|
|
string name = headerOrder[index1];
|
|
string str2 = nameValueCollection.Get(name);
|
|
if (str2 != null)
|
|
{
|
|
stringList.Add(name + ": " + str2.Trim());
|
|
nameValueCollection.Remove(name);
|
|
}
|
|
checked { ++index1; }
|
|
}
|
|
try
|
|
{
|
|
foreach (object key in nameValueCollection.Keys)
|
|
{
|
|
string str2 = Conversions.ToString(key);
|
|
string str3 = nameValueCollection.Get(str2);
|
|
if (string.Compare(str2, "Set-Cookie", StringComparison.InvariantCultureIgnoreCase) == 0)
|
|
{
|
|
string[] values2 = nameValueCollection.GetValues(str2);
|
|
int index2 = 0;
|
|
while (index2 < values2.Length)
|
|
{
|
|
string str4 = values2[index2];
|
|
stringList.Add(str2 + ": " + str4.Trim());
|
|
checked { ++index2; }
|
|
}
|
|
}
|
|
else
|
|
stringList.Add(str2 + ": " + str3.Trim());
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
//IEnumerator enumerator;
|
|
//if (enumerator is IDisposable)
|
|
// (enumerator as IDisposable).Dispose();
|
|
}
|
|
stringList.Add("");
|
|
stringList.Add("");
|
|
this._res_headers = string.Join("\r\n", stringList.ToArray());
|
|
byte[] bytes = Encoding.UTF8.GetBytes(this._res_headers);
|
|
this._st.BeginWrite(bytes, 0, bytes.Length, new AsyncCallback(this.OnSend_Header), (object) myAsyncResult);
|
|
return (IAsyncResult) myAsyncResult;
|
|
}
|
|
|
|
private void OnSend_Header(IAsyncResult asyncresult)
|
|
{
|
|
MyAsyncResult asyncState = (MyAsyncResult) asyncresult.AsyncState;
|
|
if (!asyncresult.CompletedSynchronously)
|
|
asyncState.SetAsync();
|
|
try
|
|
{
|
|
this._st.EndWrite(asyncresult);
|
|
}
|
|
catch (Exception ex1)
|
|
{
|
|
ProjectData.SetProjectError(ex1);
|
|
Exception ex2 = ex1;
|
|
asyncState.Complete(ex2);
|
|
ProjectData.ClearProjectError();
|
|
return;
|
|
}
|
|
asyncState.Complete();
|
|
}
|
|
|
|
public Stream EndSendResponse(IAsyncResult asyncresult)
|
|
{
|
|
MyAsyncResult myAsyncResult = (MyAsyncResult) asyncresult;
|
|
myAsyncResult.AsyncEnd();
|
|
myAsyncResult.ReturnValue = (object) new MyHttpServerConnection.ResponseStream(this);
|
|
object syncobject = this._syncobject;
|
|
ObjectFlowControl.CheckForSyncLockOnValueType(syncobject);
|
|
Monitor.Enter(syncobject);
|
|
try
|
|
{
|
|
this._res_state = MyHttpServerConnection.StreamStateType.HeaderFinished;
|
|
if (this._res_bodylengthtype != MyHttpServerConnection.BodyLengthType.NoBody)
|
|
{
|
|
if (this._res_bodylengthtype == MyHttpServerConnection.BodyLengthType.ContentLength)
|
|
{
|
|
if (this._res_contentlength != 0L)
|
|
goto label_6;
|
|
}
|
|
else
|
|
goto label_6;
|
|
}
|
|
this._res_state = MyHttpServerConnection.StreamStateType.BodyFinished;
|
|
}
|
|
finally
|
|
{
|
|
Monitor.Exit(syncobject);
|
|
}
|
|
label_6:
|
|
return (Stream) myAsyncResult.ReturnValue;
|
|
}
|
|
|
|
private long ResponseStreamLength()
|
|
{
|
|
object syncobject = this._syncobject;
|
|
ObjectFlowControl.CheckForSyncLockOnValueType(syncobject);
|
|
Monitor.Enter(syncobject);
|
|
try
|
|
{
|
|
if (this._res_state < MyHttpServerConnection.StreamStateType.HeaderFinished)
|
|
throw new InvalidOperationException();
|
|
}
|
|
finally
|
|
{
|
|
Monitor.Exit(syncobject);
|
|
}
|
|
return this._res_contentlength;
|
|
}
|
|
|
|
private long ResponseStreamPosition()
|
|
{
|
|
return this._res_currentposition;
|
|
}
|
|
|
|
private IAsyncResult ResponseStreamBeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
|
|
{
|
|
if (count < 0)
|
|
throw new ArgumentOutOfRangeException();
|
|
object syncobject = this._syncobject;
|
|
ObjectFlowControl.CheckForSyncLockOnValueType(syncobject);
|
|
Monitor.Enter(syncobject);
|
|
try
|
|
{
|
|
if (this._res_state == MyHttpServerConnection.StreamStateType.BodyFinished)
|
|
throw new InvalidOperationException("message body is finished");
|
|
if (this._res_state != MyHttpServerConnection.StreamStateType.HeaderFinished)
|
|
throw new InvalidOperationException();
|
|
this._res_state = MyHttpServerConnection.StreamStateType.Changing;
|
|
}
|
|
finally
|
|
{
|
|
Monitor.Exit(syncobject);
|
|
}
|
|
MyAsyncResult myAsyncResult = new MyAsyncResult(callback, RuntimeHelpers.GetObjectValue(state));
|
|
MyHttpServerConnection.StreamReadWriteParameter readWriteParameter = new MyHttpServerConnection.StreamReadWriteParameter();
|
|
readWriteParameter.buffer = buffer;
|
|
readWriteParameter.offset = offset;
|
|
readWriteParameter.count = count;
|
|
myAsyncResult.Tag = (object) readWriteParameter;
|
|
switch (this._res_bodylengthtype)
|
|
{
|
|
case MyHttpServerConnection.BodyLengthType.NoBody:
|
|
myAsyncResult.Complete();
|
|
return (IAsyncResult) myAsyncResult;
|
|
case MyHttpServerConnection.BodyLengthType.Chunk:
|
|
if (readWriteParameter.count == 0)
|
|
{
|
|
myAsyncResult.Complete();
|
|
return (IAsyncResult) myAsyncResult;
|
|
}
|
|
byte[] bytes = Encoding.UTF8.GetBytes(readWriteParameter.count.ToString("x") + "\r\n");
|
|
this._st.BeginWrite(bytes, 0, bytes.Length, new AsyncCallback(this.OnSend_Body_Chunk_Size), (object) myAsyncResult);
|
|
break;
|
|
case MyHttpServerConnection.BodyLengthType.ContentLength:
|
|
if (checked ((long) readWriteParameter.count + this._res_currentposition) > this._res_contentlength)
|
|
throw new IOException("Content length is not match");
|
|
this._st.BeginWrite(readWriteParameter.buffer, readWriteParameter.offset, readWriteParameter.count, new AsyncCallback(this.OnSend_Body_ContentLength), (object) myAsyncResult);
|
|
break;
|
|
default:
|
|
throw new Exception();
|
|
}
|
|
return (IAsyncResult) myAsyncResult;
|
|
}
|
|
|
|
private void OnSend_Body_Chunk_Size(IAsyncResult asyncresult)
|
|
{
|
|
MyAsyncResult asyncState = (MyAsyncResult) asyncresult.AsyncState;
|
|
MyHttpServerConnection.StreamReadWriteParameter tag = (MyHttpServerConnection.StreamReadWriteParameter) asyncState.Tag;
|
|
if (!asyncresult.CompletedSynchronously)
|
|
asyncState.SetAsync();
|
|
try
|
|
{
|
|
this._st.EndWrite(asyncresult);
|
|
this._st.BeginWrite(tag.buffer, tag.offset, tag.count, new AsyncCallback(this.OnSend_Body_Chunk_Data), (object) asyncState);
|
|
}
|
|
catch (Exception ex1)
|
|
{
|
|
ProjectData.SetProjectError(ex1);
|
|
Exception ex2 = ex1;
|
|
asyncState.Complete(ex2);
|
|
ProjectData.ClearProjectError();
|
|
}
|
|
}
|
|
|
|
private void OnSend_Body_Chunk_Data(IAsyncResult asyncresult)
|
|
{
|
|
MyAsyncResult asyncState = (MyAsyncResult) asyncresult.AsyncState;
|
|
MyHttpServerConnection.StreamReadWriteParameter tag = (MyHttpServerConnection.StreamReadWriteParameter) asyncState.Tag;
|
|
if (!asyncresult.CompletedSynchronously)
|
|
asyncState.SetAsync();
|
|
try
|
|
{
|
|
this._st.EndWrite(asyncresult);
|
|
this._res_currentposition = checked (this._res_currentposition + (long) tag.count);
|
|
byte[] buffer = new byte[2]{ (byte) 13, (byte) 10 };
|
|
this._st.BeginWrite(buffer, 0, buffer.Length, new AsyncCallback(this.OnSend_Body_Chunk_Data_End), (object) asyncState);
|
|
}
|
|
catch (Exception ex1)
|
|
{
|
|
ProjectData.SetProjectError(ex1);
|
|
Exception ex2 = ex1;
|
|
asyncState.Complete(ex2);
|
|
ProjectData.ClearProjectError();
|
|
}
|
|
}
|
|
|
|
private void OnSend_Body_Chunk_Data_End(IAsyncResult asyncresult)
|
|
{
|
|
MyAsyncResult asyncState = (MyAsyncResult) asyncresult.AsyncState;
|
|
MyHttpServerConnection.StreamReadWriteParameter tag = (MyHttpServerConnection.StreamReadWriteParameter) asyncState.Tag;
|
|
if (!asyncresult.CompletedSynchronously)
|
|
asyncState.SetAsync();
|
|
try
|
|
{
|
|
this._st.EndWrite(asyncresult);
|
|
object syncobject = this._syncobject;
|
|
ObjectFlowControl.CheckForSyncLockOnValueType(syncobject);
|
|
Monitor.Enter(syncobject);
|
|
try
|
|
{
|
|
this._res_state = MyHttpServerConnection.StreamStateType.HeaderFinished;
|
|
}
|
|
finally
|
|
{
|
|
Monitor.Exit(syncobject);
|
|
}
|
|
}
|
|
catch (Exception ex1)
|
|
{
|
|
ProjectData.SetProjectError(ex1);
|
|
Exception ex2 = ex1;
|
|
asyncState.Complete(ex2);
|
|
ProjectData.ClearProjectError();
|
|
return;
|
|
}
|
|
asyncState.Complete();
|
|
}
|
|
|
|
private void OnSend_Body_ContentLength(IAsyncResult asyncresult)
|
|
{
|
|
MyAsyncResult asyncState = (MyAsyncResult) asyncresult.AsyncState;
|
|
MyHttpServerConnection.StreamReadWriteParameter tag = (MyHttpServerConnection.StreamReadWriteParameter) asyncState.Tag;
|
|
if (!asyncresult.CompletedSynchronously)
|
|
asyncState.SetAsync();
|
|
try
|
|
{
|
|
this._st.EndWrite(asyncresult);
|
|
this._res_currentposition = checked (this._res_currentposition + (long) tag.count);
|
|
object syncobject = this._syncobject;
|
|
ObjectFlowControl.CheckForSyncLockOnValueType(syncobject);
|
|
Monitor.Enter(syncobject);
|
|
try
|
|
{
|
|
if (this._res_currentposition == this._res_contentlength)
|
|
this._res_state = MyHttpServerConnection.StreamStateType.BodyFinished;
|
|
else if (this._res_currentposition > this._res_contentlength)
|
|
asyncState.Complete(new Exception());
|
|
else
|
|
this._res_state = MyHttpServerConnection.StreamStateType.HeaderFinished;
|
|
}
|
|
finally
|
|
{
|
|
Monitor.Exit(syncobject);
|
|
}
|
|
}
|
|
catch (Exception ex1)
|
|
{
|
|
ProjectData.SetProjectError(ex1);
|
|
Exception ex2 = ex1;
|
|
asyncState.Complete(ex2);
|
|
ProjectData.ClearProjectError();
|
|
return;
|
|
}
|
|
asyncState.Complete();
|
|
}
|
|
|
|
private void ResponseStreamEndWrite(IAsyncResult asyncResult)
|
|
{
|
|
((MyAsyncResult) asyncResult).AsyncEnd();
|
|
}
|
|
|
|
internal void RequestStreamClose()
|
|
{
|
|
this._req_closed = true;
|
|
if (!this._res_closed)
|
|
return;
|
|
this.CloseSeries();
|
|
}
|
|
|
|
private void ResponseStreamClose()
|
|
{
|
|
object syncobject = this._syncobject;
|
|
ObjectFlowControl.CheckForSyncLockOnValueType(syncobject);
|
|
Monitor.Enter(syncobject);
|
|
try
|
|
{
|
|
if (this._res_state == MyHttpServerConnection.StreamStateType.HeaderFinished && this._res_bodylengthtype == MyHttpServerConnection.BodyLengthType.Chunk)
|
|
{
|
|
this._res_state = MyHttpServerConnection.StreamStateType.Changing;
|
|
byte[] bytes = Encoding.UTF8.GetBytes("0\r\n\r\n");
|
|
this._st.EndWrite(this._st.BeginWrite(bytes, 0, bytes.Length, (AsyncCallback) null, (object) null));
|
|
this._res_state = MyHttpServerConnection.StreamStateType.BodyFinished;
|
|
}
|
|
else if (this._res_bodylengthtype == MyHttpServerConnection.BodyLengthType.ContentLength)
|
|
{
|
|
if (this._res_state != MyHttpServerConnection.StreamStateType.BodyFinished)
|
|
throw new Exception();
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
Monitor.Exit(syncobject);
|
|
}
|
|
this._res_closed = true;
|
|
if (!this._req_closed)
|
|
return;
|
|
this.CloseSeries();
|
|
}
|
|
|
|
private void CloseSeries()
|
|
{
|
|
if (!this._res_closed || !this._req_closed)
|
|
return;
|
|
this._needclose = this._needclose | this._req_state != MyHttpServerConnection.StreamStateType.BodyFinished;
|
|
this._needclose = this._needclose | this._res_state != MyHttpServerConnection.StreamStateType.BodyFinished;
|
|
if (this._needclose)
|
|
{
|
|
this._st.Close();
|
|
this._st = (LineReadableSocketStream) null;
|
|
this._isconnected = false;
|
|
}
|
|
else
|
|
{
|
|
object syncobject = this._syncobject;
|
|
ObjectFlowControl.CheckForSyncLockOnValueType(syncobject);
|
|
Monitor.Enter(syncobject);
|
|
try
|
|
{
|
|
this._res_currentposition = 0L;
|
|
this._req_currentposition = 0L;
|
|
this._req_currentchunksize = 0;
|
|
this._req_closed = false;
|
|
this._res_closed = false;
|
|
this._req_state = MyHttpServerConnection.StreamStateType.Initial;
|
|
this._res_state = MyHttpServerConnection.StreamStateType.Initial;
|
|
}
|
|
finally
|
|
{
|
|
Monitor.Exit(syncobject);
|
|
}
|
|
}
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
string str = base.ToString();
|
|
if (!this.IsConnected)
|
|
return str + "\r\nDicsonnected";
|
|
return str + "\r\n" + this._remoteep.ToString() + "\r\n" + this._req_state.ToString();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Dispose(true);
|
|
}
|
|
|
|
private enum BodyLengthType
|
|
{
|
|
Unknown,
|
|
NoBody,
|
|
Chunk,
|
|
ContentLength,
|
|
Connection,
|
|
}
|
|
|
|
private enum StreamStateType
|
|
{
|
|
Changing,
|
|
Initial,
|
|
HeaderFinished,
|
|
BodyFinished,
|
|
}
|
|
|
|
private class StreamReadWriteParameter
|
|
{
|
|
public byte[] buffer;
|
|
public int offset;
|
|
public int count;
|
|
|
|
[DebuggerNonUserCode]
|
|
public StreamReadWriteParameter()
|
|
{
|
|
}
|
|
}
|
|
|
|
private class RequestStream : Stream
|
|
{
|
|
private MyHttpServerConnection _owner;
|
|
|
|
public RequestStream(MyHttpServerConnection owner)
|
|
{
|
|
this._owner = owner;
|
|
}
|
|
|
|
public override void Close()
|
|
{
|
|
if (this._owner != null)
|
|
this._owner.RequestStreamClose();
|
|
this._owner = (MyHttpServerConnection) null;
|
|
base.Close();
|
|
}
|
|
|
|
public override bool CanRead
|
|
{
|
|
get
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public override bool CanSeek
|
|
{
|
|
get
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public override bool CanWrite
|
|
{
|
|
get
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public override void Flush()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override long Seek(long offset, SeekOrigin origin)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override void SetLength(long value)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override void Write(byte[] buffer, int offset, int count)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override long Length
|
|
{
|
|
get
|
|
{
|
|
if (this._owner == null)
|
|
throw new ObjectDisposedException(this.ToString());
|
|
return this._owner.RequestStreamLength();
|
|
}
|
|
}
|
|
|
|
public override long Position
|
|
{
|
|
get
|
|
{
|
|
if (this._owner == null)
|
|
throw new ObjectDisposedException(this.ToString());
|
|
return this._owner.RequestStreamPosition();
|
|
}
|
|
set
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
|
|
public override int Read(byte[] buffer, int offset, int count)
|
|
{
|
|
IAsyncResult asyncResult = this._owner.RequestStreamBeginRead(buffer, offset, count, (AsyncCallback) null, (object) null);
|
|
if (!asyncResult.CompletedSynchronously && !asyncResult.AsyncWaitHandle.WaitOne(this._owner.ReadTimeout, false))
|
|
throw new IOException("Timeout");
|
|
return this._owner.RequestStreamEndRead(asyncResult);
|
|
}
|
|
|
|
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
|
|
{
|
|
return this._owner.RequestStreamBeginRead(buffer, offset, count, callback, RuntimeHelpers.GetObjectValue(state));
|
|
}
|
|
|
|
public override int EndRead(IAsyncResult asyncResult)
|
|
{
|
|
return this._owner.RequestStreamEndRead(asyncResult);
|
|
}
|
|
|
|
public override int ReadTimeout
|
|
{
|
|
get
|
|
{
|
|
return this._owner.ReadTimeout;
|
|
}
|
|
set
|
|
{
|
|
this._owner.ReadTimeout = value;
|
|
}
|
|
}
|
|
|
|
public override int WriteTimeout
|
|
{
|
|
get
|
|
{
|
|
return this._owner.WriteTimeout;
|
|
}
|
|
set
|
|
{
|
|
this._owner.WriteTimeout = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
private class ResponseStream : Stream
|
|
{
|
|
private MyHttpServerConnection _owner;
|
|
|
|
public ResponseStream(MyHttpServerConnection owner)
|
|
{
|
|
this._owner = owner;
|
|
}
|
|
|
|
public override void Close()
|
|
{
|
|
if (this._owner != null)
|
|
this._owner.ResponseStreamClose();
|
|
this._owner = (MyHttpServerConnection) null;
|
|
base.Close();
|
|
}
|
|
|
|
public override bool CanRead
|
|
{
|
|
get
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public override bool CanSeek
|
|
{
|
|
get
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public override bool CanWrite
|
|
{
|
|
get
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public override void Flush()
|
|
{
|
|
}
|
|
|
|
public override long Seek(long offset, SeekOrigin origin)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override void SetLength(long value)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override long Length
|
|
{
|
|
get
|
|
{
|
|
if (this._owner == null)
|
|
throw new ObjectDisposedException(this.ToString());
|
|
return this._owner.ResponseStreamLength();
|
|
}
|
|
}
|
|
|
|
public override long Position
|
|
{
|
|
get
|
|
{
|
|
if (this._owner == null)
|
|
throw new ObjectDisposedException(this.ToString());
|
|
return this._owner.ResponseStreamPosition();
|
|
}
|
|
set
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
|
|
public override int Read(byte[] buffer, int offset, int count)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override void Write(byte[] buffer, int offset, int count)
|
|
{
|
|
IAsyncResult asyncResult = this._owner.ResponseStreamBeginWrite(buffer, offset, count, (AsyncCallback) null, (object) null);
|
|
if (!asyncResult.CompletedSynchronously && !asyncResult.AsyncWaitHandle.WaitOne(this._owner.WriteTimeout, false))
|
|
throw new IOException("Timeout");
|
|
this._owner.ResponseStreamEndWrite(asyncResult);
|
|
}
|
|
|
|
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
|
|
{
|
|
return this._owner.ResponseStreamBeginWrite(buffer, offset, count, callback, RuntimeHelpers.GetObjectValue(state));
|
|
}
|
|
|
|
public override void EndWrite(IAsyncResult asyncResult)
|
|
{
|
|
this._owner.ResponseStreamEndWrite(asyncResult);
|
|
}
|
|
|
|
public override int ReadTimeout
|
|
{
|
|
get
|
|
{
|
|
return this._owner.ReadTimeout;
|
|
}
|
|
set
|
|
{
|
|
this._owner.ReadTimeout = value;
|
|
}
|
|
}
|
|
|
|
public override int WriteTimeout
|
|
{
|
|
get
|
|
{
|
|
return this._owner.WriteTimeout;
|
|
}
|
|
set
|
|
{
|
|
this._owner.WriteTimeout = value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|