2005-06-10 Gonzalo Paniagua Javier <gonzalo@ximian.com>
authorGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Fri, 10 Jun 2005 17:53:44 +0000 (17:53 -0000)
committerGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Fri, 10 Jun 2005 17:53:44 +0000 (17:53 -0000)
* WebConnection.cs:
* HttpWebRequest.cs:
* WebConnectionStream.cs: initiate the polling for input data after
sending the header so that we detect any response that the server sends
back even if we're still trying to write the request for a POST/PUT.
If we get the response (or an error) before any one calls GetResponse(),
keep it around instead of ignoring it.

svn path=/trunk/mcs/; revision=45785

mcs/class/System/System.Net/ChangeLog
mcs/class/System/System.Net/HttpWebRequest.cs
mcs/class/System/System.Net/WebConnection.cs
mcs/class/System/System.Net/WebConnectionStream.cs

index dd073f9cd9dc81c8d07d6ffa3b501921f938af9e..8b31985a365c0aa123627861d9412cc76c270057 100644 (file)
@@ -1,3 +1,13 @@
+2005-06-10 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * WebConnection.cs:
+       * HttpWebRequest.cs:
+       * WebConnectionStream.cs: initiate the polling for input data after
+       sending the header so that we detect any response that the server sends
+       back even if we're still trying to write the request for a POST/PUT.
+       If we get the response (or an error) before any one calls GetResponse(),
+       keep it around instead of ignoring it.
+
 2005-06-03 Gonzalo Paniagua Javier <gonzalo@ximian.com>
 
        * HttpWebRequest.cs: send the right header/user/password in
index 1f4ee5af8cd1e397be56e6f34033adc7573184ba..109533d06a970f9c5646d7713b2916f0a08522d7 100644 (file)
@@ -90,6 +90,7 @@ namespace System.Net
                byte[] bodyBuffer;
                int bodyBufferLength;
                bool getResponseCalled;
+               Exception saved_exc;
 #if NET_1_1
                int maxResponseHeadersLength;
                static int defaultMaxResponseHeadersLength;
@@ -664,8 +665,13 @@ namespace System.Net
                        initialMethod = method;
                        if (haveResponse) {
                                if (webResponse != null) {
+                                       Exception saved = saved_exc;
                                        Monitor.Exit (this);
-                                       asyncRead.SetCompleted (true, webResponse);
+                                       if (saved == null) {
+                                               asyncRead.SetCompleted (true, webResponse);
+                                       } else {
+                                               asyncRead.SetCompleted (true, saved);
+                                       }
                                        asyncRead.DoCallback ();
                                        return asyncRead;
                                }
@@ -704,9 +710,6 @@ namespace System.Net
 
                public override WebResponse GetResponse()
                {
-                       if (haveResponse && webResponse != null)
-                               return webResponse;
-
                        WebAsyncResult result = (WebAsyncResult) BeginGetResponse (null, null);
                        return EndGetResponse (result);
                }
@@ -1008,7 +1011,21 @@ namespace System.Net
                                asyncWrite = null;
                        }
                }
-               
+
+               void CheckSendError (WebConnectionData data)
+               {
+                       // Got here, but no one called GetResponse
+                       if (data.StatusCode < 400)
+                               return;
+
+                       if (writeStream != null && asyncRead == null && !writeStream.CompleteRequestWritten) {
+                               // The request has not been completely sent and we got here!
+                               // We should probably just close and cause an error in any case,
+                               saved_exc = new WebException (data.StatusDescription, null, WebExceptionStatus.ProtocolError, webResponse); 
+                               webResponse.ReadAll ();
+                       }
+               }
+
                internal void SetResponseData (WebConnectionData data)
                {
                        if (aborted) {
@@ -1027,6 +1044,14 @@ namespace System.Net
                                        data.stream.Close ();
                        }
 
+                       if (wexc == null && (method == "POST" || method == "PUT")) {
+                               lock (this) {
+                                       CheckSendError (data);
+                                       if (saved_exc != null)
+                                               wexc = (WebException) saved_exc;
+                               }
+                       }
+
                        WebAsyncResult r = asyncRead;
                        if (r != null) {
                                if (wexc != null) {
index e570fa4f9741b4c287320f229e6ffb8755fed198..7f2c8bc69985a3b5d22937c457083b404e46b0b8 100644 (file)
@@ -764,10 +764,18 @@ namespace System.Net
                        return result;
                }
 
-               internal void EndWrite (IAsyncResult result)
+               internal bool EndWrite (IAsyncResult result)
                {
-                       if (nstream != null)
+                       if (nstream == null)
+                               return false;
+
+                       try {
                                nstream.EndWrite (result);
+                               return true;
+                       } catch (Exception e) {
+                               status = WebExceptionStatus.SendFailure;
+                               return false;
+                       }
                }
 
                internal int Read (byte [] buffer, int offset, int size)
index c573017124e4472a9d5bbdec19f1094192022795..a2b64f53c6ea32da04b7171587de00d41e2a9af9 100644 (file)
@@ -60,6 +60,7 @@ namespace System.Net
                object locker = new object ();
                bool initRead;
                bool read_eof;
+               bool complete_request_written;
 
                public WebConnectionStream (WebConnection cnc)
                {
@@ -96,6 +97,10 @@ namespace System.Net
                                pending = new ManualResetEvent (true);
                }
 
+               internal bool CompleteRequestWritten {
+                       get { return complete_request_written; }
+               }
+
                internal bool SendChunked {
                        set { sendChunked = value; }
                }
@@ -513,14 +518,28 @@ namespace System.Net
                        if (cnc.Data.StatusCode != 0 && cnc.Data.StatusCode != 100)
                                return;
 
-                       cnc.Write (bytes, 0, length);
+                       if (!initRead) {
+                               initRead = true;
+                               WebConnection.InitRead (cnc);
+                       }
+
+                       IAsyncResult result = cnc.BeginWrite (bytes, 0, length, null, null);
+                       complete_request_written = cnc.EndWrite (result);
                }
 
                internal void InternalClose ()
                {
                        disposed = true;
                }
-               
+
+               internal void ForceCloseConnection ()
+               {
+                       if (!disposed) {
+                               disposed = true;
+                               cnc.Close (true);
+                       }
+               }
+
                public override void Close ()
                {
                        if (sendChunked) {
@@ -541,6 +560,7 @@ namespace System.Net
                                }
                                return;
                        } else if (!allowBuffering) {
+                               complete_request_written = true;
                                if (!initRead) {
                                        initRead = true;
                                        WebConnection.InitRead (cnc);
@@ -551,17 +571,12 @@ namespace System.Net
                        if (disposed)
                                return;
 
-                       disposed = true;
-
                        long length = request.ContentLength;
                        if (length != -1 && length > writeBuffer.Length)
                                throw new IOException ("Cannot close the stream until all bytes are written");
 
                        WriteRequest ();
-                       if (!initRead) {
-                               initRead = true;
-                               WebConnection.InitRead (cnc);
-                       }
+                       disposed = true;
                }
 
                public override long Seek (long a, SeekOrigin b)