summaryrefslogtreecommitdiff
path: root/mcs/class/System/System.Net
diff options
context:
space:
mode:
Diffstat (limited to 'mcs/class/System/System.Net')
-rw-r--r--mcs/class/System/System.Net/HttpWebRequest.cs41
-rw-r--r--mcs/class/System/System.Net/HttpWebResponse.cs3
-rw-r--r--mcs/class/System/System.Net/IPAddress.cs10
-rw-r--r--mcs/class/System/System.Net/MacProxy.cs86
-rw-r--r--mcs/class/System/System.Net/ServicePointManager.cs5
-rw-r--r--mcs/class/System/System.Net/TransportContext.cs2
-rw-r--r--mcs/class/System/System.Net/WebConnection.cs27
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 ();