Convert blocking operations in HttpWebRequest and SslClientStream to non-blocking...
[mono.git] / mcs / class / System / System.Net / HttpWebRequest.cs
index 84d59f6802517fa65be1681fc9cf57f1d8940597..6aee5af52bd3bda083667b07cc29d699d178f597 100644 (file)
@@ -1163,7 +1163,9 @@ namespace System.Net
                        bool spoint10 = (proto_version == null || proto_version == HttpVersion.Version10);
 
                        if (keepAlive && (version == HttpVersion.Version10 || spoint10)) {
-                               webHeaders.RemoveAndAdd (connectionHeader, "keep-alive");
+                               if (webHeaders[connectionHeader] == null
+                                   || webHeaders[connectionHeader].IndexOf ("keep-alive", StringComparison.OrdinalIgnoreCase) == -1)
+                                       webHeaders.RemoveAndAdd (connectionHeader, "keep-alive");
                        } else if (!keepAlive && version == HttpVersion.Version11) {
                                webHeaders.RemoveAndAdd (connectionHeader, "close");
                        }
@@ -1230,7 +1232,7 @@ namespace System.Net
                        }
                }
 
-               internal void SendRequestHeaders (bool propagate_error)
+               internal byte[] GetRequestHeaders ()
                {
                        StringBuilder req = new StringBuilder ();
                        string query;
@@ -1252,18 +1254,7 @@ namespace System.Net
                                                                actualVersion.Major, actualVersion.Minor);
                        req.Append (GetHeaders ());
                        string reqstr = req.ToString ();
-                       byte [] bytes = Encoding.UTF8.GetBytes (reqstr);
-                       try {
-                               writeStream.SetHeaders (bytes);
-                       } catch (WebException wexc) {
-                               SetWriteStreamError (wexc.Status, wexc);
-                               if (propagate_error)
-                                       throw;
-                       } catch (Exception exc) {
-                               SetWriteStreamError (WebExceptionStatus.SendFailure, exc);
-                               if (propagate_error)
-                                       throw;
-                       }
+                       return Encoding.UTF8.GetBytes (reqstr);
                }
 
                internal void SetWriteStream (WebConnectionStream stream)
@@ -1278,14 +1269,32 @@ namespace System.Net
                                writeStream.SendChunked = false;
                        }
 
-                       SendRequestHeaders (false);
+                       byte[] requestHeaders = GetRequestHeaders ();
+                       WebAsyncResult result = new WebAsyncResult (new AsyncCallback (SetWriteStreamCB), null);
+                       writeStream.SetHeadersAsync (requestHeaders, result);
+               }
+
+               void SetWriteStreamCB(IAsyncResult ar)
+               {
+                       WebAsyncResult result = ar as WebAsyncResult;
 
+                       if (result.Exception != null) {
+                               WebException wexc = result.Exception as WebException;
+                               if (wexc != null) {
+                                       SetWriteStreamError (wexc.Status, wexc);
+                                       return;
+                               }
+                               SetWriteStreamError (WebExceptionStatus.SendFailure, result.Exception);
+                               return;
+                       }
+               
                        haveRequest = true;
-                       
+
                        if (bodyBuffer != null) {
                                // The body has been written and buffered. The request "user"
                                // won't write it again, so we must do it.
                                if (ntlm_auth_state != NtlmAuthState.Challenge) {
+                                       // FIXME: this is a blocking call on the thread pool that could lead to thread pool exhaustion
                                        writeStream.Write (bodyBuffer, 0, bodyBufferLength);
                                        bodyBuffer = null;
                                        writeStream.Close ();
@@ -1293,11 +1302,12 @@ namespace System.Net
                        } else if (method != "HEAD" && method != "GET" && method != "MKCOL" && method != "CONNECT" &&
                                        method != "TRACE") {
                                if (getResponseCalled && !writeStream.RequestWritten)
+                                       // FIXME: this is a blocking call on the thread pool that could lead to thread pool exhaustion
                                        writeStream.WriteRequest ();
                        }
 
                        if (asyncWrite != null) {
-                               asyncWrite.SetCompleted (false, stream);
+                               asyncWrite.SetCompleted (false, writeStream);
                                asyncWrite.DoCallback ();
                                asyncWrite = null;
                        }
@@ -1605,6 +1615,13 @@ namespace System.Net
 
                        throw throwMe;
                }
+
+               internal bool ReuseConnection {
+                       get;
+                       set;
+               }
+
+               internal WebConnection StoredConnection;
        }
 }