Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Read system proxy information on macOS #36177

Merged
merged 5 commits into from
Apr 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/Common/src/Interop/OSX/Interop.CoreFoundation.CFArray.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,16 @@ namespace Microsoft.Win32.SafeHandles
{
internal sealed class SafeCFArrayHandle : SafeHandle
{
internal SafeCFArrayHandle()
private SafeCFArrayHandle()
: base(IntPtr.Zero, ownsHandle: true)
{
}

internal SafeCFArrayHandle(IntPtr handle, bool ownsHandle)
: base(handle, ownsHandle)
{
}

protected override bool ReleaseHandle()
{
Interop.CoreFoundation.CFRelease(handle);
Expand Down
43 changes: 43 additions & 0 deletions src/Common/src/Interop/OSX/Interop.CoreFoundation.CFDictionary.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32.SafeHandles;

internal static partial class Interop
{
internal static partial class CoreFoundation
{
[DllImport(Libraries.CoreFoundationLibrary)]
internal static extern IntPtr CFDictionaryGetValue(SafeCFDictionaryHandle handle, IntPtr key);
}
}

namespace Microsoft.Win32.SafeHandles
{
internal sealed class SafeCFDictionaryHandle : SafeHandle
{
private SafeCFDictionaryHandle()
: base(IntPtr.Zero, ownsHandle: true)
{
}

internal SafeCFDictionaryHandle(IntPtr handle, bool ownsHandle)
: base(handle, ownsHandle)
{
}

protected override bool ReleaseHandle()
{
Interop.CoreFoundation.CFRelease(handle);
SetHandle(IntPtr.Zero);
return true;
}

public override bool IsInvalid => handle == IntPtr.Zero;
}
}
23 changes: 23 additions & 0 deletions src/Common/src/Interop/OSX/Interop.CoreFoundation.CFNumber.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32.SafeHandles;

internal static partial class Interop
{
internal static partial class CoreFoundation
{
internal enum CFNumberType
{
kCFNumberIntType = 9,
}

[DllImport(Libraries.CoreFoundationLibrary)]
private static extern int CFNumberGetValue(IntPtr handle, CFNumberType type, out int value);
}
}
145 changes: 145 additions & 0 deletions src/Common/src/Interop/OSX/Interop.CoreFoundation.CFProxy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32.SafeHandles;

using CFRunLoopSourceRef = System.IntPtr;

internal static partial class Interop
{
internal static partial class CoreFoundation
{
[DllImport(Libraries.CFNetworkLibrary)]
internal static extern SafeCFDictionaryHandle CFNetworkCopySystemProxySettings();

[DllImport(Libraries.CFNetworkLibrary)]
internal static extern SafeCFArrayHandle CFNetworkCopyProxiesForURL(SafeCreateHandle url, SafeCFDictionaryHandle proxySettings);

internal delegate void CFProxyAutoConfigurationResultCallback(IntPtr client, IntPtr proxyList, IntPtr error);

[DllImport(Libraries.CFNetworkLibrary)]
internal static extern CFRunLoopSourceRef CFNetworkExecuteProxyAutoConfigurationURL(
IntPtr proxyAutoConfigURL,
SafeCreateHandle targetURL,
CFProxyAutoConfigurationResultCallback cb,
ref CFStreamClientContext clientContext);

[DllImport(Libraries.CFNetworkLibrary)]
internal static extern CFRunLoopSourceRef CFNetworkExecuteProxyAutoConfigurationScript(
IntPtr proxyAutoConfigurationScript,
SafeCreateHandle targetURL,
CFProxyAutoConfigurationResultCallback cb,
ref CFStreamClientContext clientContext);

[StructLayout(LayoutKind.Sequential)]
internal struct CFStreamClientContext
{
public IntPtr Version;
public IntPtr Info;
public IntPtr Retain;
public IntPtr Release;
public IntPtr CopyDescription;
}

internal class CFProxy
{
private SafeCFDictionaryHandle _dictionary;

internal static readonly string kCFProxyTypeAutoConfigurationURL;
internal static readonly string kCFProxyTypeAutoConfigurationJavaScript;
internal static readonly string kCFProxyTypeFTP;
internal static readonly string kCFProxyTypeHTTP;
internal static readonly string kCFProxyTypeHTTPS;
internal static readonly string kCFProxyTypeSOCKS;

private static readonly IntPtr kCFProxyAutoConfigurationJavaScriptKey;
private static readonly IntPtr kCFProxyAutoConfigurationURLKey;
private static readonly IntPtr kCFProxyHostNameKey;
private static readonly IntPtr kCFProxyPasswordKey;
private static readonly IntPtr kCFProxyPortNumberKey;
private static readonly IntPtr kCFProxyTypeKey;
private static readonly IntPtr kCFProxyUsernameKey;

static CFProxy()
{
IntPtr lib = NativeLibrary.Load(Interop.Libraries.CFNetworkLibrary);
if (lib != IntPtr.Zero)
{
kCFProxyTypeAutoConfigurationURL = LoadCFStringSymbol(lib, "kCFProxyTypeAutoConfigurationURL");
kCFProxyTypeAutoConfigurationJavaScript = LoadCFStringSymbol(lib, "kCFProxyTypeAutoConfigurationJavaScript");
kCFProxyTypeFTP = LoadCFStringSymbol(lib, "kCFProxyTypeFTP");
kCFProxyTypeHTTP = LoadCFStringSymbol(lib, "kCFProxyTypeHTTP");
kCFProxyTypeHTTPS = LoadCFStringSymbol(lib, "kCFProxyTypeHTTPS");
kCFProxyTypeSOCKS = LoadCFStringSymbol(lib, "kCFProxyTypeSOCKS");

kCFProxyAutoConfigurationJavaScriptKey = LoadSymbol(lib, "kCFProxyAutoConfigurationJavaScriptKey");
kCFProxyAutoConfigurationURLKey = LoadSymbol(lib, "kCFProxyAutoConfigurationURLKey");
kCFProxyHostNameKey = LoadSymbol(lib, "kCFProxyHostNameKey");
kCFProxyPasswordKey = LoadSymbol(lib, "kCFProxyPasswordKey");
kCFProxyPortNumberKey = LoadSymbol(lib, "kCFProxyPortNumberKey");
kCFProxyTypeKey = LoadSymbol(lib, "kCFProxyTypeKey");
kCFProxyUsernameKey = LoadSymbol(lib, "kCFProxyUsernameKey");
}
}

public CFProxy(SafeCFDictionaryHandle dictionary)
{
_dictionary = dictionary;
}

private static IntPtr LoadSymbol(IntPtr lib, string name)
{
IntPtr indirect = NativeLibrary.GetExport(lib, name);
return indirect == IntPtr.Zero ? IntPtr.Zero : Marshal.ReadIntPtr(indirect);
filipnavara marked this conversation as resolved.
Show resolved Hide resolved
}

private static string LoadCFStringSymbol(IntPtr lib, string name)
{
using (SafeCFStringHandle cfString = new SafeCFStringHandle(LoadSymbol(lib, name), false))
{
Debug.Assert(!cfString.IsInvalid);
return Interop.CoreFoundation.CFStringToString(cfString);
}
}

private string GetString(IntPtr key)
{
IntPtr dictValue = CFDictionaryGetValue(_dictionary, key);
if (dictValue != IntPtr.Zero)
{
using (SafeCFStringHandle handle = new SafeCFStringHandle(dictValue, false))
{
return CFStringToString(handle);
}
}
return null;
}

public string ProxyType => GetString(kCFProxyTypeKey);
public string HostName => GetString(kCFProxyHostNameKey);
public string Username => GetString(kCFProxyUsernameKey);
public string Password => GetString(kCFProxyPasswordKey);

public int PortNumber
{
get
{
IntPtr dictValue = CFDictionaryGetValue(_dictionary, kCFProxyPortNumberKey);
if (dictValue != IntPtr.Zero && CFNumberGetValue(dictValue, CFNumberType.kCFNumberIntType, out int value) > 0)
{
return value;
}
return -1;
}
}

public IntPtr AutoConfigurationURL => CFDictionaryGetValue(_dictionary, kCFProxyAutoConfigurationURLKey);
public IntPtr AutoConfigurationJavaScript => CFDictionaryGetValue(_dictionary, kCFProxyAutoConfigurationJavaScriptKey);
}
}
}
5 changes: 5 additions & 0 deletions src/Common/src/Interop/OSX/Interop.CoreFoundation.CFString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ internal SafeCFStringHandle()
{
}

internal SafeCFStringHandle(IntPtr handle, bool ownsHandle)
: base(handle, ownsHandle)
{
}

protected override bool ReleaseHandle()
{
Interop.CoreFoundation.CFRelease(handle);
Expand Down
30 changes: 30 additions & 0 deletions src/Common/src/Interop/OSX/Interop.CoreFoundation.CFUrl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32.SafeHandles;

internal static partial class Interop
{
internal static partial class CoreFoundation
{
[DllImport(Libraries.CoreFoundationLibrary)]
private static extern SafeCreateHandle CFURLCreateWithString(
IntPtr allocator,
SafeCreateHandle str,
IntPtr baseUrl);

internal static SafeCreateHandle CFURLCreateWithString(string url)
{
Debug.Assert(url != null);
using (SafeCreateHandle stringHandle = CFStringCreateWithCString(url))
{
return CFURLCreateWithString(IntPtr.Zero, stringHandle, IntPtr.Zero);
}
}
}
}
3 changes: 2 additions & 1 deletion src/Common/src/Interop/OSX/Interop.Libraries.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ internal static partial class Interop
internal static partial class Libraries
{
internal const string CoreFoundationLibrary = "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation";
internal const string CoreServicesLibrary = "/System/Library/Frameworks/CoreServices.framework/CoreServices";
internal const string CoreServicesLibrary = "/System/Library/Frameworks/CoreServices.framework/CoreServices";
internal const string CFNetworkLibrary = "/System/Library/Frameworks/CFNetwork.framework/CFNetwork";
internal const string libproc = "libproc";
internal const string LibSystemCommonCrypto = "/usr/lib/system/libcommonCrypto";
internal const string LibSystemKernel = "/usr/lib/system/libsystem_kernel";
Expand Down
15 changes: 14 additions & 1 deletion src/Common/src/Interop/OSX/Interop.RunLoop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ internal static partial class RunLoop
#endif
internal extern static void CFRunLoopRun();

/// <summary>
/// Runs the current thread’s CFRunLoop object in a particular mode.
/// </summary>
[DllImport(Interop.Libraries.CoreFoundationLibrary)]
internal extern static int CFRunLoopRunInMode(CFStringRef mode, double seconds, int returnAfterSourceHandled);

/// <summary>
/// Notifies a RunLoop to stop and return control to the execution context that called CFRunLoopRun
/// </summary>
Expand Down Expand Up @@ -66,7 +72,14 @@ internal static partial class RunLoop
/// <param name="mode">The run loop mode of rl from which to remove source.</param>
[DllImport(Interop.Libraries.CoreFoundationLibrary)]
internal static extern void CFRunLoopRemoveSource(CFRunLoopRef rl, CFRunLoopSourceRef source, CFStringRef mode);


/// <summary>
/// Invalidates a CFRunLoopSource object, stopping it from ever firing again.
/// </summary>
/// <param name="source">The run loop source to invalidate.</param>
[DllImport(Interop.Libraries.CoreFoundationLibrary)]
internal static extern void CFRunLoopSourceInvalidate(CFRunLoopSourceRef source);

/// <summary>
/// Returns a bool that indicates whether the run loop is waiting for an event.
/// </summary>
Expand Down
44 changes: 43 additions & 1 deletion src/System.Net.Http/src/System.Net.Http.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,6 @@
</ItemGroup>
<!-- SocketsHttpHandler platform parts -->
<ItemGroup Condition=" '$(TargetsUnix)' == 'true' And '$(TargetGroup)' == 'netcoreapp'">
<Compile Include="System\Net\Http\SocketsHttpHandler\SystemProxyInfo.Unix.cs" />
<Compile Include="System\Net\Http\SocketsHttpHandler\HttpEnvironmentProxy.cs" />
<Compile Include="$(CommonPath)\System\Net\ContextAwareResult.Unix.cs">
<Link>Common\System\Net\ContextAwareResult.Unix.cs</Link>
Expand Down Expand Up @@ -256,6 +255,49 @@
<Link>Common\System\Net\Security\Unix\SafeDeleteNegoContext.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup Condition=" '$(TargetsUnix)' == 'true' And '$(TargetsOSX)' != 'true' And '$(TargetGroup)' == 'netcoreapp'">
<Compile Include="System\Net\Http\SocketsHttpHandler\SystemProxyInfo.Unix.cs" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetsOSX)' == 'true' And '$(TargetGroup)' == 'netcoreapp'">
<Compile Include="System\Net\Http\SocketsHttpHandler\SystemProxyInfo.OSX.cs" />
<Compile Include="System\Net\Http\SocketsHttpHandler\MacProxy.cs" />
<Compile Include="$(CommonPath)\Interop\OSX\Interop.CoreFoundation.cs">
<Link>Common\Interop\OSX\Interop.CoreFoundation.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\OSX\Interop.CoreFoundation.CFArray.cs">
<Link>Common\Interop\OSX\Interop.CoreFoundation.CFArray.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\OSX\Interop.CoreFoundation.CFData.cs">
<Link>Common\Interop\OSX\Interop.CoreFoundation.CFData.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\OSX\Interop.CoreFoundation.CFDictionary.cs">
<Link>Common\Interop\OSX\Interop.CoreFoundation.CFDictionary.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\OSX\Interop.CoreFoundation.CFProxy.cs">
<Link>Common\Interop\OSX\Interop.CoreFoundation.CFProxy.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\OSX\Interop.CoreFoundation.CFUrl.cs">
<Link>Common\Interop\OSX\Interop.CoreFoundation.CFUrl.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\OSX\Interop.CoreFoundation.CFString.cs">
<Link>Common\Interop\OSX\Interop.CoreFoundation.CFString.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\OSX\Interop.CoreFoundation.CFNumber.cs">
<Link>Common\Interop\OSX\Interop.CoreFoundation.CFString.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\OSX\Interop.CoreFoundation.CFError.cs">
<Link>Common\Interop\OSX\Interop.CoreFoundation.CFError.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\OSX\Interop.RunLoop.cs">
<Link>Common\Interop\OSX\Interop.RunLoop.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\OSX\Interop.Libraries.cs">
<Link>Common\Interop\OSX\Interop.Libraries.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Microsoft\Win32\SafeHandles\SafeCreateHandle.OSX.cs">
<Link>Common\Microsoft\Win32\SafeHandles\SafeCreateHandle.OSX.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup Condition=" '$(TargetsWindows)' == 'true' And '$(TargetGroup)' == 'netcoreapp'">
<Compile Include="System\Net\Http\SocketsHttpHandler\SystemProxyInfo.Windows.cs" />
<Compile Include="System\Net\Http\SocketsHttpHandler\HttpSystemProxy.cs" />
Expand Down
Loading