diff options
Diffstat (limited to 'mcs/class/System/System.Net')
-rw-r--r-- | mcs/class/System/System.Net/HttpWebRequest.cs | 41 | ||||
-rw-r--r-- | mcs/class/System/System.Net/HttpWebResponse.cs | 3 | ||||
-rw-r--r-- | mcs/class/System/System.Net/IPAddress.cs | 10 | ||||
-rw-r--r-- | mcs/class/System/System.Net/MacProxy.cs | 86 | ||||
-rw-r--r-- | mcs/class/System/System.Net/ServicePointManager.cs | 5 | ||||
-rw-r--r-- | mcs/class/System/System.Net/TransportContext.cs | 2 | ||||
-rw-r--r-- | mcs/class/System/System.Net/WebConnection.cs | 27 |
7 files changed, 140 insertions, 34 deletions
diff --git a/mcs/class/System/System.Net/HttpWebRequest.cs b/mcs/class/System/System.Net/HttpWebRequest.cs index 84d59f6802..1cdffff533 100644 --- a/mcs/class/System/System.Net/HttpWebRequest.cs +++ b/mcs/class/System/System.Net/HttpWebRequest.cs @@ -36,6 +36,7 @@ using System.Collections; using System.Configuration; using System.Globalization; using System.IO; +using System.Net; using System.Net.Cache; using System.Net.Sockets; using System.Runtime.Remoting.Messaging; @@ -950,6 +951,14 @@ namespace System.Net return result.Response; } + +#if NET_3_5 + public Stream EndGetRequestStream (IAsyncResult asyncResult, out TransportContext transportContext) + { + transportContext = null; + return EndGetRequestStream (asyncResult); + } +#endif public override WebResponse GetResponse() { @@ -1071,29 +1080,19 @@ namespace System.Net redirects++; Exception e = null; string uriString = null; - switch (code) { case HttpStatusCode.Ambiguous: // 300 e = new WebException ("Ambiguous redirect."); break; case HttpStatusCode.MovedPermanently: // 301 case HttpStatusCode.Redirect: // 302 - case HttpStatusCode.TemporaryRedirect: // 307 - /* MS follows the redirect for POST too - if (method != "GET" && method != "HEAD") // 10.3 - return false; - */ - - contentLength = -1; - bodyBufferLength = 0; - bodyBuffer = null; - if (code != HttpStatusCode.TemporaryRedirect) + if (method == "POST") method = "GET"; - uriString = webResponse.Headers ["Location"]; + break; + case HttpStatusCode.TemporaryRedirect: // 307 break; case HttpStatusCode.SeeOther: //303 method = "GET"; - uriString = webResponse.Headers ["Location"]; break; case HttpStatusCode.NotModified: // 304 return false; @@ -1109,6 +1108,11 @@ namespace System.Net if (e != null) throw e; + //contentLength = -1; + //bodyBufferLength = 0; + //bodyBuffer = null; + uriString = webResponse.Headers ["Location"]; + if (uriString == null) throw new WebException ("No Location header found for " + (int) code, WebExceptionStatus.ProtocolError); @@ -1163,7 +1167,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"); } @@ -1605,6 +1611,13 @@ namespace System.Net throw throwMe; } + + internal bool ReuseConnection { + get; + set; + } + + internal WebConnection StoredConnection; } } diff --git a/mcs/class/System/System.Net/HttpWebResponse.cs b/mcs/class/System/System.Net/HttpWebResponse.cs index 0cb3cd8c85..2b756a97bd 100644 --- a/mcs/class/System/System.Net/HttpWebResponse.cs +++ b/mcs/class/System/System.Net/HttpWebResponse.cs @@ -277,7 +277,7 @@ namespace System.Net CheckDisposed (); if (stream == null) return Stream.Null; - if (0 == String.Compare (method, "HEAD", true)) // see par 4.3 & 9.4 + if (string.Equals (method, "HEAD", StringComparison.OrdinalIgnoreCase)) // see par 4.3 & 9.4 return Stream.Null; return stream; @@ -319,7 +319,6 @@ namespace System.Net void IDisposable.Dispose () { Dispose (true); - GC.SuppressFinalize (this); } #if NET_4_0 diff --git a/mcs/class/System/System.Net/IPAddress.cs b/mcs/class/System/System.Net/IPAddress.cs index 2dd7d1ab31..92c0f8e6e0 100644 --- a/mcs/class/System/System.Net/IPAddress.cs +++ b/mcs/class/System/System.Net/IPAddress.cs @@ -333,6 +333,16 @@ namespace System.Net { } } +#if NET_4_0 + public bool IsIPv6Teredo { + get { + return m_Family != AddressFamily.InterNetwork && + NetworkToHostOrder ((short) m_Numbers [0]) == 0x2001 && + m_Numbers[1] == 0; + } + } +#endif + public long ScopeId { get { if (m_Family != AddressFamily.InterNetworkV6) diff --git a/mcs/class/System/System.Net/MacProxy.cs b/mcs/class/System/System.Net/MacProxy.cs index a21cf97c65..1a5e89ec0a 100644 --- a/mcs/class/System/System.Net/MacProxy.cs +++ b/mcs/class/System/System.Net/MacProxy.cs @@ -25,7 +25,9 @@ // using System; +using System.Collections.Generic; using System.Runtime.InteropServices; +using System.Threading; namespace System.Net { @@ -606,13 +608,87 @@ namespace System.Net public const string CFNetworkLibrary = "/System/Library/Frameworks/CFNetwork.framework/CFNetwork"; #endif - [DllImport (CFNetworkLibrary)] - // CFArrayRef CFNetworkCopyProxiesForAutoConfigurationScript (CFStringRef proxyAutoConfigurationScript, CFURLRef targetURL); - extern static IntPtr CFNetworkCopyProxiesForAutoConfigurationScript (IntPtr proxyAutoConfigurationScript, IntPtr targetURL); - + [DllImport (CFNetworkLibrary, EntryPoint = "CFNetworkCopyProxiesForAutoConfigurationScript")] + // CFArrayRef CFNetworkCopyProxiesForAutoConfigurationScript (CFStringRef proxyAutoConfigurationScript, CFURLRef targetURL, CFErrorRef* error); + extern static IntPtr CFNetworkCopyProxiesForAutoConfigurationScriptSequential (IntPtr proxyAutoConfigurationScript, IntPtr targetURL, out IntPtr error); + + class GetProxyData : IDisposable { + public IntPtr script; + public IntPtr targetUri; + public IntPtr error; + public IntPtr result; + public ManualResetEvent evt = new ManualResetEvent (false); + + public void Dispose () + { + evt.Close (); + } + } + + static object lock_obj = new object (); + static Queue<GetProxyData> get_proxy_queue; + static AutoResetEvent proxy_event; + + static void CFNetworkCopyProxiesForAutoConfigurationScriptThread () + { + GetProxyData data; + var data_left = true; + + while (true) { + proxy_event.WaitOne (); + + do { + lock (lock_obj) { + if (get_proxy_queue.Count == 0) + break; + data = get_proxy_queue.Dequeue (); + data_left = get_proxy_queue.Count > 0; + } + + data.result = CFNetworkCopyProxiesForAutoConfigurationScriptSequential (data.script, data.targetUri, out data.error); + data.evt.Set (); + } while (data_left); + } + } + + static IntPtr CFNetworkCopyProxiesForAutoConfigurationScript (IntPtr proxyAutoConfigurationScript, IntPtr targetURL, out IntPtr error) + { + // This method must only be called on only one thread during an application's life time. + // Note that it's not enough to use a lock to make calls sequential across different threads, + // it has to be one thread. Also note that that thread can't be the main thread, because the + // main thread might be blocking waiting for this network request to finish. + // Another possibility would be to use JavaScriptCore to execute this piece of + // javascript ourselves, but unfortunately it's not available before iOS7. + // See bug #7923 comment #21+. + + using (var data = new GetProxyData ()) { + data.script = proxyAutoConfigurationScript; + data.targetUri = targetURL; + + lock (lock_obj) { + if (get_proxy_queue == null) { + get_proxy_queue = new Queue<GetProxyData> (); + proxy_event = new AutoResetEvent (false); + new Thread (CFNetworkCopyProxiesForAutoConfigurationScriptThread) { + IsBackground = true, + }.Start (); + } + get_proxy_queue.Enqueue (data); + proxy_event.Set (); + } + + data.evt.WaitOne (); + + error = data.error; + + return data.result; + } + } + static CFArray CopyProxiesForAutoConfigurationScript (IntPtr proxyAutoConfigurationScript, CFUrl targetURL) { - IntPtr native = CFNetworkCopyProxiesForAutoConfigurationScript (proxyAutoConfigurationScript, targetURL.Handle); + IntPtr err = IntPtr.Zero; + IntPtr native = CFNetworkCopyProxiesForAutoConfigurationScript (proxyAutoConfigurationScript, targetURL.Handle, out err); if (native == IntPtr.Zero) return null; diff --git a/mcs/class/System/System.Net/ServicePointManager.cs b/mcs/class/System/System.Net/ServicePointManager.cs index a6d456293e..27e9893a80 100644 --- a/mcs/class/System/System.Net/ServicePointManager.cs +++ b/mcs/class/System/System.Net/ServicePointManager.cs @@ -326,7 +326,8 @@ namespace System.Net if (address == null) throw new ArgumentNullException ("address"); - RecycleServicePoints (); + if ((servicePoints.Count % 4) == 0) + RecycleServicePoints (); var origAddress = new Uri (address.Scheme + "://" + address.Authority); @@ -346,8 +347,8 @@ namespace System.Net address = new Uri (address.Scheme + "://" + address.Authority); ServicePoint sp = null; + SPKey key = new SPKey (origAddress, usesProxy ? address : null, useConnect); lock (servicePoints) { - SPKey key = new SPKey (origAddress, usesProxy ? address : null, useConnect); sp = servicePoints [key] as ServicePoint; if (sp != null) return sp; diff --git a/mcs/class/System/System.Net/TransportContext.cs b/mcs/class/System/System.Net/TransportContext.cs index 04d534fa13..e0366bb0db 100644 --- a/mcs/class/System/System.Net/TransportContext.cs +++ b/mcs/class/System/System.Net/TransportContext.cs @@ -26,7 +26,7 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#if NET_4_0 +#if NET_3_5 using System.Security.Authentication.ExtendedProtection; diff --git a/mcs/class/System/System.Net/WebConnection.cs b/mcs/class/System/System.Net/WebConnection.cs index 7f09859cb5..7f65751c67 100644 --- a/mcs/class/System/System.Net/WebConnection.cs +++ b/mcs/class/System/System.Net/WebConnection.cs @@ -62,7 +62,7 @@ namespace System.Net { ServicePoint sPoint; Stream nstream; - Socket socket; + internal Socket socket; object socketLock = new object (); WebExceptionStatus status; WaitCallback initConn; @@ -613,16 +613,16 @@ namespace System.Net return (statusCode >= 200 && statusCode != 204 && statusCode != 304); } - internal void GetCertificates () + internal void GetCertificates (Stream stream) { // here the SSL negotiation have been done #if SECURITY_DEP && MONOTOUCH - HttpsClientStream s = (nstream as HttpsClientStream); + HttpsClientStream s = (stream as HttpsClientStream); X509Certificate client = s.SelectedClientCertificate; X509Certificate server = s.ServerCertificate; #else - X509Certificate client = (X509Certificate) piClient.GetValue (nstream, null); - X509Certificate server = (X509Certificate) piServer.GetValue (nstream, null); + X509Certificate client = (X509Certificate) piClient.GetValue (stream, null); + X509Certificate server = (X509Certificate) piServer.GetValue (stream, null); #endif sPoint.SetCertificates (client, server); certsAvailable = (server != null); @@ -750,6 +750,8 @@ namespace System.Net { HttpWebRequest request = (HttpWebRequest) state; request.WebConnection = this; + if (request.ReuseConnection) + request.StoredConnection = this; if (request.Aborted) return; @@ -1142,16 +1144,16 @@ namespace System.Net lock (this) { if (Data.request != request) throw new ObjectDisposedException (typeof (NetworkStream).FullName); - if (nstream == null) - return false; s = nstream; + if (s == null) + return false; } try { s.Write (buffer, offset, size); // here SSL handshake should have been done if (ssl && !certsAvailable) - GetCertificates (); + GetCertificates (s); } catch (Exception e) { err_msg = e.Message; WebExceptionStatus wes = WebExceptionStatus.SendFailure; @@ -1164,10 +1166,10 @@ namespace System.Net // if SSL is in use then check for TrustFailure if (ssl) { #if SECURITY_DEP && MONOTOUCH - HttpsClientStream https = (nstream as HttpsClientStream); + HttpsClientStream https = (s as HttpsClientStream); if (https.TrustFailure) { #else - if ((bool) piTrustFailure.GetValue (nstream, null)) { + if ((bool) piTrustFailure.GetValue (s , null)) { #endif wes = WebExceptionStatus.TrustFailure; msg = "Trust failure"; @@ -1183,6 +1185,11 @@ namespace System.Net internal void Close (bool sendNext) { lock (this) { + if (Data != null && Data.request != null && Data.request.ReuseConnection) { + Data.request.ReuseConnection = false; + return; + } + if (nstream != null) { try { nstream.Close (); |