WebAsyncResult asyncWrite;
WebAsyncResult asyncRead;
EventHandler abortHandler;
- bool aborted;
+ int aborted;
bool gotRequestStream;
int redirects;
bool expectContinue;
object locker = new object ();
bool is_ntlm_auth;
bool finished_reading;
+ internal WebConnection WebConnection;
#if NET_2_0
DecompressionMethods auto_decomp;
#endif
public override IAsyncResult BeginGetRequestStream (AsyncCallback callback, object state)
{
- if (aborted)
+ if (Aborted)
throw new WebException ("The request was canceled.", WebExceptionStatus.RequestCanceled);
bool send = !(method == "GET" || method == "CONNECT" || method == "HEAD" ||
public override IAsyncResult BeginGetResponse (AsyncCallback callback, object state)
{
- if (aborted)
+ if (Aborted)
throw new WebException ("The request was canceled.", WebExceptionStatus.RequestCanceled);
if (method == null)
}
internal bool Aborted {
- get { return aborted; }
+ get { return Interlocked.CompareExchange (ref aborted, 0, 0) == 1; }
}
public override void Abort ()
{
- if (aborted)
+ if (Interlocked.CompareExchange (ref aborted, 1, 0) == 1)
return;
- aborted = true;
if (haveResponse && finished_reading)
return;
internal void SetWriteStreamError (WebExceptionStatus status, Exception exc)
{
- if (aborted)
+ if (Aborted)
return;
WebAsyncResult r = asyncWrite;
internal void SetWriteStream (WebConnectionStream stream)
{
- if (aborted)
+ if (Aborted)
return;
writeStream = stream;
internal void SetResponseError (WebExceptionStatus status, Exception e, string where)
{
- if (aborted)
+ if (Aborted)
return;
lock (locker) {
string msg = String.Format ("Error getting response stream ({0}): {1}", where, status);
internal void SetResponseData (WebConnectionData data)
{
lock (locker) {
- if (aborted) {
+ if (Aborted) {
if (data.stream != null)
data.stream.Close ();
return;
Headers,
Content
}
-
+
class WebConnection
{
ServicePoint sPoint;
byte [] buffer;
static AsyncCallback readDoneDelegate = new AsyncCallback (ReadDone);
EventHandler abortHandler;
+ AbortHelper abortHelper;
ReadState readState;
internal WebConnectionData Data;
bool chunkedRead;
readState = ReadState.None;
Data = new WebConnectionData ();
initConn = new WaitCallback (InitConnection);
- abortHandler = new EventHandler (Abort);
queue = group.Queue;
+ abortHelper = new AbortHelper ();
+ abortHelper.Connection = this;
+ abortHandler = new EventHandler (abortHelper.Abort);
+ }
+
+ class AbortHelper {
+ public WebConnection Connection;
+
+ public void Abort (object sender, EventArgs args)
+ {
+ WebConnection other = ((HttpWebRequest) sender).WebConnection;
+ if (other == null)
+ other = Connection;
+ other.Abort (sender, args);
+ }
}
bool CanReuse ()
return (socket.Poll (0, SelectMode.SelectRead) == false);
}
- void Connect ()
+ void Connect (HttpWebRequest request)
{
lock (socketLock) {
if (socket != null && socket.Connected && status == WebExceptionStatus.Success) {
return;
}
+ WebConnectionData data = Data;
foreach (IPAddress address in hostEntry.AddressList) {
socket = new Socket (address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
} else {
#endif
try {
- if (Data.request == null || Data.request.Aborted)
+ if (request.Aborted)
return;
socket.Connect (remote);
status = WebExceptionStatus.Success;
break;
+ } catch (ThreadAbortException) {
+ // program exiting...
+ Socket s = socket;
+ socket = null;
+ if (s != null)
+ s.Close ();
+ return;
+ } catch (ObjectDisposedException exc) {
+ // socket closed from another thread
+ return;
} catch (Exception exc) {
- // This might be null if the request is aborted
- if (socket != null) {
- socket.Close ();
- socket = null;
+ Socket s = socket;
+ socket = null;
+ if (s != null)
+ s.Close ();
+ if (!request.Aborted)
status = WebExceptionStatus.ConnectFailure;
- connect_exception = exc;
- }
+ connect_exception = exc;
}
#if NET_2_0
}
nstream = serverStream;
}
} catch (Exception) {
- status = WebExceptionStatus.ConnectFailure;
+ if (!request.Aborted)
+ status = WebExceptionStatus.ConnectFailure;
return false;
}
void InitConnection (object state)
{
HttpWebRequest request = (HttpWebRequest) state;
+ request.WebConnection = this;
- if (status == WebExceptionStatus.RequestCanceled) {
- lock (this) {
- busy = false;
- Data = new WebConnectionData ();
- SendNext ();
- }
+ if (request.Aborted)
return;
- }
keepAlive = request.KeepAlive;
Data = new WebConnectionData ();
Data.request = request;
retry:
- Connect ();
+ Connect (request);
+ if (request.Aborted)
+ return;
+
if (status != WebExceptionStatus.Success) {
- if (status != WebExceptionStatus.RequestCanceled) {
+ if (!request.Aborted) {
request.SetWriteStreamError (status, connect_exception);
Close (true);
}
}
if (!CreateStream (request)) {
+ if (request.Aborted)
+ return;
+
+ WebExceptionStatus st = status;
if (Data.Challenge != null)
goto retry;
Exception cnc_exc = connect_exception;
connect_exception = null;
- request.SetWriteStreamError (status, cnc_exc);
+ request.SetWriteStreamError (st, cnc_exc);
Close (true);
return;
}
internal EventHandler SendRequest (HttpWebRequest request)
{
+ if (request.Aborted)
+ return null;
+
lock (this) {
if (!busy) {
busy = true;
lock (queue) {
HttpWebRequest req = (HttpWebRequest) sender;
if (Data.request == req) {
- if (!Data.request.FinishedReading)
- HandleError (WebExceptionStatus.RequestCanceled, null, "Abort");
+ if (!req.FinishedReading) {
+ status = WebExceptionStatus.RequestCanceled;
+ Close (false);
+ Data = new WebConnectionData ();
+ if (queue.Count > 0) {
+ Data.request = (HttpWebRequest) queue.Dequeue ();
+ SendRequest (Data.request);
+ }
+ }
return;
- } else if (Data.request == null && socket != null) {
- Socket s = socket;
- socket = null;
- s.Close ();
}
req.FinishedReading = true;
req.SetResponseError (WebExceptionStatus.RequestCanceled, null, "User aborted");
if (queue.Count > 0 && queue.Peek () == sender) {
queue.Dequeue ();
- } else {
+ } else if (queue.Count > 0) {
object [] old = queue.ToArray ();
queue.Clear ();
for (int i = old.Length - 1; i >= 0; i--) {
queue.Enqueue (old [i]);
}
}
- if (queue.Count == 0)
- Close (false);
}
}
}