MemoryMappedFile support on Windows
[mono.git] / mcs / class / System / System.Net / MacProxy.cs
index 1a5e89ec0a36e8571f3750c8f7091ff635d8b5b1..8294f7b43d2574ac4142bfd1dc19476032484160 100644 (file)
@@ -3,7 +3,7 @@
 //  
 // Author: Jeffrey Stedfast <jeff@xamarin.com>
 // 
-// Copyright (c) 2012 Xamarin Inc.
+// Copyright (c) 2012-2014 Xamarin Inc.
 // 
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
 // 
 
 using System;
+using System.Net;
 using System.Collections.Generic;
 using System.Runtime.InteropServices;
 using System.Threading;
 
-namespace System.Net
+namespace Mono.Net
 {
        internal class CFObject : IDisposable
        {
@@ -83,7 +84,7 @@ namespace System.Net
                }
 
                [DllImport (CoreFoundationLibrary)]
-               extern static IntPtr CFRelease (IntPtr handle);
+               extern static void CFRelease (IntPtr handle);
 
                void Release ()
                {
@@ -110,7 +111,7 @@ namespace System.Net
                public CFArray (IntPtr handle, bool own) : base (handle, own) { }
 
                [DllImport (CoreFoundationLibrary)]
-               extern static IntPtr CFArrayCreate (IntPtr allocator, IntPtr values, int numValues, IntPtr callbacks);
+               extern static IntPtr CFArrayCreate (IntPtr allocator, IntPtr values, /* CFIndex */ IntPtr numValues, IntPtr callbacks);
                static readonly IntPtr kCFTypeArrayCallbacks;
 
                static CFArray ()
@@ -132,7 +133,7 @@ namespace System.Net
                                throw new ArgumentNullException ("values");
 
                        fixed (IntPtr *pv = values) {
-                               IntPtr handle = CFArrayCreate (IntPtr.Zero, (IntPtr) pv, values.Length, kCFTypeArrayCallbacks);
+                               IntPtr handle = CFArrayCreate (IntPtr.Zero, (IntPtr) pv, (IntPtr) values.Length, kCFTypeArrayCallbacks);
 
                                return new CFArray (handle, false);
                        }
@@ -151,18 +152,18 @@ namespace System.Net
                }
 
                [DllImport (CoreFoundationLibrary)]
-               extern static int CFArrayGetCount (IntPtr handle);
+               extern static /* CFIndex */ IntPtr CFArrayGetCount (IntPtr handle);
 
                public int Count {
-                       get { return CFArrayGetCount (Handle); }
+                       get { return (int) CFArrayGetCount (Handle); }
                }
 
                [DllImport (CoreFoundationLibrary)]
-               extern static IntPtr CFArrayGetValueAtIndex (IntPtr handle, int index);
+               extern static IntPtr CFArrayGetValueAtIndex (IntPtr handle, /* CFIndex */ IntPtr index);
 
                public IntPtr this[int index] {
                        get {
-                               return CFArrayGetValueAtIndex (Handle, index);
+                               return CFArrayGetValueAtIndex (Handle, (IntPtr) index);
                        }
                }
        }
@@ -172,7 +173,8 @@ namespace System.Net
                public CFNumber (IntPtr handle, bool own) : base (handle, own) { }
 
                [DllImport (CoreFoundationLibrary)]
-               extern static bool CFNumberGetValue (IntPtr handle, int type, out bool value);
+               [return: MarshalAs (UnmanagedType.I1)]
+               extern static bool CFNumberGetValue (IntPtr handle, /* CFNumberType */ IntPtr type, [MarshalAs (UnmanagedType.I1)] out bool value);
 
                public static bool AsBool (IntPtr handle)
                {
@@ -181,7 +183,7 @@ namespace System.Net
                        if (handle == IntPtr.Zero)
                                return false;
 
-                       CFNumberGetValue (handle, 1, out value);
+                       CFNumberGetValue (handle, (IntPtr) 1, out value);
 
                        return value;
                }
@@ -192,7 +194,8 @@ namespace System.Net
                }
 
                [DllImport (CoreFoundationLibrary)]
-               extern static bool CFNumberGetValue (IntPtr handle, int type, out int value);
+               [return: MarshalAs (UnmanagedType.I1)]
+               extern static bool CFNumberGetValue (IntPtr handle, /* CFNumberType */ IntPtr type, out int value);
 
                public static int AsInt32 (IntPtr handle)
                {
@@ -201,7 +204,8 @@ namespace System.Net
                        if (handle == IntPtr.Zero)
                                return 0;
 
-                       CFNumberGetValue (handle, 9, out value);
+                       // 9 == kCFNumberIntType == C int
+                       CFNumberGetValue (handle, (IntPtr) 9, out value);
 
                        return value;
                }
@@ -213,15 +217,23 @@ namespace System.Net
        }
 
        internal struct CFRange {
-               public int Location, Length;
+               public IntPtr Location, Length;
                
                public CFRange (int loc, int len)
                {
-                       Location = loc;
-                       Length = len;
+                       Location = (IntPtr) loc;
+                       Length = (IntPtr) len;
                }
        }
 
+       internal struct CFStreamClientContext {
+               public IntPtr Version;
+               public IntPtr Info;
+               public IntPtr Retain;
+               public IntPtr Release;
+               public IntPtr CopyDescription;
+       }
+
        internal class CFString : CFObject
        {
                string str;
@@ -229,7 +241,7 @@ namespace System.Net
                public CFString (IntPtr handle, bool own) : base (handle, own) { }
 
                [DllImport (CoreFoundationLibrary)]
-               extern static IntPtr CFStringCreateWithCharacters (IntPtr alloc, IntPtr chars, int length);
+               extern static IntPtr CFStringCreateWithCharacters (IntPtr alloc, IntPtr chars, /* CFIndex */ IntPtr length);
 
                public static CFString Create (string value)
                {
@@ -237,7 +249,7 @@ namespace System.Net
 
                        unsafe {
                                fixed (char *ptr = value) {
-                                       handle = CFStringCreateWithCharacters (IntPtr.Zero, (IntPtr) ptr, value.Length);
+                                       handle = CFStringCreateWithCharacters (IntPtr.Zero, (IntPtr) ptr, (IntPtr) value.Length);
                                }
                        }
 
@@ -248,14 +260,14 @@ namespace System.Net
                }
 
                [DllImport (CoreFoundationLibrary)]
-               extern static int CFStringGetLength (IntPtr handle);
+               extern static /* CFIndex */ IntPtr CFStringGetLength (IntPtr handle);
 
                public int Length {
                        get {
                                if (str != null)
                                        return str.Length;
 
-                               return CFStringGetLength (Handle);
+                               return (int) CFStringGetLength (Handle);
                        }
                }
 
@@ -270,7 +282,7 @@ namespace System.Net
                        if (handle == IntPtr.Zero)
                                return null;
                        
-                       int len = CFStringGetLength (handle);
+                       int len = (int) CFStringGetLength (handle);
                        
                        if (len == 0)
                                return string.Empty;
@@ -358,6 +370,52 @@ namespace System.Net
                }
        }
 
+       internal class CFRunLoop : CFObject
+       {
+               [DllImport (CFObject.CoreFoundationLibrary)]
+               static extern void CFRunLoopAddSource (IntPtr rl, IntPtr source, IntPtr mode);
+
+               [DllImport (CFObject.CoreFoundationLibrary)]
+               static extern void CFRunLoopRemoveSource (IntPtr rl, IntPtr source, IntPtr mode);
+
+               [DllImport (CFObject.CoreFoundationLibrary)]
+               static extern int CFRunLoopRunInMode (IntPtr mode, double seconds, bool returnAfterSourceHandled);
+
+               [DllImport (CFObject.CoreFoundationLibrary)]
+               static extern IntPtr CFRunLoopGetCurrent ();
+
+               [DllImport (CFObject.CoreFoundationLibrary)]
+               static extern void CFRunLoopStop (IntPtr rl);
+
+               public CFRunLoop (IntPtr handle, bool own): base (handle, own)
+               {
+               }
+
+               public static CFRunLoop CurrentRunLoop {
+                       get { return new CFRunLoop (CFRunLoopGetCurrent (), false); }
+               }
+
+               public void AddSource (IntPtr source, CFString mode)
+               {
+                       CFRunLoopAddSource (Handle, source, mode.Handle);
+               }
+
+               public void RemoveSource (IntPtr source, CFString mode)
+               {
+                       CFRunLoopRemoveSource (Handle, source, mode.Handle);
+               }
+
+               public int RunInMode (CFString mode, double seconds, bool returnAfterSourceHandled)
+               {
+                       return CFRunLoopRunInMode (mode.Handle, seconds, returnAfterSourceHandled);
+               }
+
+               public void Stop ()
+               {
+                       CFRunLoopStop (Handle);
+               }
+       }
+
        internal enum CFProxyType {
                None,
                AutoConfigurationUrl,
@@ -612,6 +670,10 @@ namespace System.Net
                // CFArrayRef CFNetworkCopyProxiesForAutoConfigurationScript (CFStringRef proxyAutoConfigurationScript, CFURLRef targetURL, CFErrorRef* error);
                extern static IntPtr CFNetworkCopyProxiesForAutoConfigurationScriptSequential (IntPtr proxyAutoConfigurationScript, IntPtr targetURL, out IntPtr error);
 
+               [DllImport (CFNetworkLibrary)]
+               extern static IntPtr CFNetworkExecuteProxyAutoConfigurationURL (IntPtr proxyAutoConfigURL, IntPtr targetURL, CFProxyAutoConfigurationResultCallback cb, ref CFStreamClientContext clientContext);
+
+
                class GetProxyData : IDisposable {
                        public IntPtr script;
                        public IntPtr targetUri;
@@ -734,6 +796,45 @@ namespace System.Net
                        
                        return proxies;
                }
+
+               delegate void CFProxyAutoConfigurationResultCallback (IntPtr client, IntPtr proxyList, IntPtr error);
+
+               public static CFProxy[] ExecuteProxyAutoConfigurationURL (IntPtr proxyAutoConfigURL, Uri targetURL)
+               {
+                       CFUrl url = CFUrl.Create (targetURL.AbsoluteUri);
+                       if (url == null)
+                               return null;
+
+                       CFProxy[] proxies = null;
+
+                       var runLoop = CFRunLoop.CurrentRunLoop;
+
+                       // Callback that will be called after executing the configuration script
+                       CFProxyAutoConfigurationResultCallback cb = delegate (IntPtr client, IntPtr proxyList, IntPtr error) {
+                               if (proxyList != IntPtr.Zero) {
+                                       var array = new CFArray (proxyList, false);
+                                       proxies = new CFProxy [array.Count];
+                                       for (int i = 0; i < proxies.Length; i++) {
+                                               CFDictionary dict = new CFDictionary (array[i], false);
+                                               proxies[i] = new CFProxy (dict);
+                                       }
+                                       array.Dispose ();
+                               }
+                               runLoop.Stop ();
+                       };
+
+                       var clientContext = new CFStreamClientContext ();
+                       var loopSource = CFNetworkExecuteProxyAutoConfigurationURL (proxyAutoConfigURL, url.Handle, cb, ref clientContext);
+
+                       // Create a private mode
+                       var mode = CFString.Create ("Mono.MacProxy");
+
+                       runLoop.AddSource (loopSource, mode);
+                       runLoop.RunInMode (mode, double.MaxValue, false);
+                       runLoop.RemoveSource (loopSource, mode);
+
+                       return proxies;
+               }
                
                [DllImport (CFNetworkLibrary)]
                // CFArrayRef CFNetworkCopyProxiesForURL (CFURLRef url, CFDictionaryRef proxySettings);
@@ -856,7 +957,18 @@ namespace System.Net
                        static Uri GetProxyUriFromScript (IntPtr script, Uri targetUri, out NetworkCredential credentials)
                        {
                                CFProxy[] proxies = CFNetwork.GetProxiesForAutoConfigurationScript (script, targetUri);
-                               
+                               return SelectProxy (proxies, targetUri, out credentials);
+                       }
+
+                       static Uri ExecuteProxyAutoConfigurationURL (IntPtr proxyAutoConfigURL, Uri targetUri, out NetworkCredential credentials)
+                       {
+                               CFProxy[] proxies = CFNetwork.ExecuteProxyAutoConfigurationURL (proxyAutoConfigURL, targetUri);
+                               return SelectProxy (proxies, targetUri, out credentials);
+                       }
+
+
+                       static Uri SelectProxy (CFProxy[] proxies, Uri targetUri, out NetworkCredential credentials)
+                       {
                                if (proxies == null) {
                                        credentials = null;
                                        return targetUri;
@@ -904,7 +1016,7 @@ namespace System.Net
                                                                proxy = GetProxyUriFromScript (proxies[i].AutoConfigurationJavaScript, targetUri, out credentials);
                                                                break;
                                                        case CFProxyType.AutoConfigurationUrl:
-                                                               // unsupported proxy type (requires fetching script from remote url)
+                                                               proxy = ExecuteProxyAutoConfigurationURL (proxies[i].AutoConfigurationUrl, targetUri, out credentials);
                                                                break;
                                                        case CFProxyType.HTTPS:
                                                        case CFProxyType.HTTP: