-
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
881 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
using System.Runtime.InteropServices; | ||
|
||
using Microsoft.Win32.SafeHandles; | ||
|
||
// Declared as signed long, which has sizeof(void*) on OSX. | ||
using CFIndex = System.IntPtr; | ||
|
||
internal static partial class Interop | ||
{ | ||
internal static partial class CoreFoundation | ||
{ | ||
[LibraryImport(Libraries.CoreFoundationLibrary, EntryPoint = "CFArrayGetCount")] | ||
private static partial CFIndex _CFArrayGetCount(SafeCFArrayHandle cfArray); | ||
|
||
// Follows the "Get" version of the "Create" rule, so needs to return an IntPtr to | ||
// prevent CFRelease from being called on the SafeHandle close. | ||
[LibraryImport(Libraries.CoreFoundationLibrary, EntryPoint = "CFArrayGetValueAtIndex")] | ||
private static partial IntPtr CFArrayGetValueAtIndex(SafeCFArrayHandle cfArray, CFIndex index); | ||
|
||
internal static long CFArrayGetCount(SafeCFArrayHandle cfArray) | ||
{ | ||
return _CFArrayGetCount(cfArray).ToInt64(); | ||
} | ||
|
||
internal static IntPtr CFArrayGetValueAtIndex(SafeCFArrayHandle cfArray, int index) | ||
{ | ||
return CFArrayGetValueAtIndex(cfArray, new CFIndex(index)); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
using System.Runtime.InteropServices; | ||
|
||
using Microsoft.Win32.SafeHandles; | ||
|
||
// Declared as signed long, which has sizeof(void*) on OSX. | ||
using CFIndex = System.IntPtr; | ||
|
||
internal static partial class Interop | ||
{ | ||
internal static partial class CoreFoundation | ||
{ | ||
[LibraryImport(Libraries.CoreFoundationLibrary)] | ||
private static unsafe partial byte* CFDataGetBytePtr(SafeCFDataHandle cfData); | ||
|
||
[LibraryImport(Libraries.CoreFoundationLibrary)] | ||
private static partial CFIndex CFDataGetLength(SafeCFDataHandle cfData); | ||
|
||
internal static unsafe Span<byte> CFDataDangerousGetSpan(SafeCFDataHandle cfData) | ||
{ | ||
long length = CFDataGetLength(cfData).ToInt64(); | ||
byte* dataBytes = CFDataGetBytePtr(cfData); | ||
return new Span<byte>(dataBytes, checked((int)length)); | ||
} | ||
|
||
internal static byte[] CFGetData(SafeCFDataHandle cfData) | ||
{ | ||
return CFDataDangerousGetSpan(cfData).ToArray(); | ||
} | ||
|
||
internal static unsafe bool TryCFWriteData(SafeCFDataHandle cfData, Span<byte> destination, out int bytesWritten) | ||
{ | ||
long length = CFDataGetLength(cfData).ToInt64(); | ||
|
||
if (length > 0) | ||
{ | ||
if (destination.Length < length) | ||
{ | ||
bytesWritten = 0; | ||
return false; | ||
} | ||
|
||
byte* dataBytes = CFDataGetBytePtr(cfData); | ||
fixed (byte* destinationPtr = &MemoryMarshal.GetReference(destination)) | ||
{ | ||
Buffer.MemoryCopy(dataBytes, destinationPtr, destination.Length, length); | ||
} | ||
} | ||
|
||
bytesWritten = (int)length; | ||
return true; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
using System.Diagnostics; | ||
using System.Runtime.InteropServices; | ||
|
||
using Microsoft.Win32.SafeHandles; | ||
|
||
#pragma warning disable SA1121 // we don't want to simplify built-ins here as we're using aliasing | ||
using CFAbsoluteTime = System.Double; | ||
|
||
internal static partial class Interop | ||
{ | ||
internal static partial class CoreFoundation | ||
{ | ||
// https://developer.apple.com/reference/corefoundation/cfabsolutetime | ||
private static readonly DateTime s_cfDateEpoch = new DateTime(2001, 1, 1, 0, 0, 0, DateTimeKind.Utc); | ||
|
||
[LibraryImport(Libraries.CoreFoundationLibrary)] | ||
private static partial SafeCFDateHandle CFDateCreate(IntPtr zero, CFAbsoluteTime at); | ||
|
||
internal static SafeCFDateHandle CFDateCreate(DateTime date) | ||
{ | ||
Debug.Assert( | ||
date.Kind != DateTimeKind.Unspecified, | ||
"DateTimeKind.Unspecified should be specified to Local or UTC by the caller"); | ||
|
||
// UTC stays unchanged, Local is changed. | ||
// Unspecified gets treated as Local (which may or may not be desired). | ||
DateTime utcDate = date.ToUniversalTime(); | ||
|
||
double epochDeltaSeconds = (utcDate - s_cfDateEpoch).TotalSeconds; | ||
|
||
SafeCFDateHandle cfDate = CFDateCreate(IntPtr.Zero, epochDeltaSeconds); | ||
|
||
if (cfDate.IsInvalid) | ||
{ | ||
cfDate.Dispose(); | ||
throw new OutOfMemoryException(); | ||
} | ||
|
||
return cfDate; | ||
} | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
src/Ultra.Core/Interop/Interop.CoreFoundation.CFDictionary.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
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 | ||
{ | ||
[LibraryImport(Libraries.CoreFoundationLibrary)] | ||
internal static partial IntPtr CFDictionaryGetValue(SafeCFDictionaryHandle handle, IntPtr key); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
using System.Diagnostics; | ||
using System.Runtime.InteropServices; | ||
|
||
using Microsoft.Win32.SafeHandles; | ||
|
||
// Declared as signed long, which has sizeof(void*) on OSX. | ||
using CFIndex = System.IntPtr; | ||
|
||
internal static partial class Interop | ||
{ | ||
internal static partial class CoreFoundation | ||
{ | ||
[LibraryImport(Libraries.CoreFoundationLibrary)] | ||
private static partial CFIndex CFErrorGetCode(SafeCFErrorHandle cfError); | ||
|
||
[LibraryImport(Libraries.CoreFoundationLibrary)] | ||
private static partial SafeCFStringHandle CFErrorCopyDescription(SafeCFErrorHandle cfError); | ||
|
||
internal static int GetErrorCode(SafeCFErrorHandle cfError) | ||
{ | ||
unchecked | ||
{ | ||
return (int)(CFErrorGetCode(cfError).ToInt64()); | ||
} | ||
} | ||
|
||
internal static string? GetErrorDescription(SafeCFErrorHandle cfError) | ||
{ | ||
if (cfError.IsInvalid) | ||
{ | ||
return null; | ||
} | ||
|
||
using SafeCFStringHandle cfString = CFErrorCopyDescription(cfError); | ||
return CFStringToString(cfString); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
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, | ||
} | ||
|
||
[LibraryImport(Libraries.CoreFoundationLibrary)] | ||
private static unsafe partial int CFNumberGetValue(IntPtr handle, CFNumberType type, int* value); | ||
} | ||
} |
150 changes: 150 additions & 0 deletions
150
src/Ultra.Core/Interop/Interop.CoreFoundation.CFProxy.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
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 | ||
{ | ||
[LibraryImport(Libraries.CFNetworkLibrary)] | ||
internal static partial SafeCFDictionaryHandle CFNetworkCopySystemProxySettings(); | ||
|
||
[LibraryImport(Libraries.CFNetworkLibrary)] | ||
internal static partial SafeCFArrayHandle CFNetworkCopyProxiesForURL(SafeCreateHandle url, SafeCFDictionaryHandle proxySettings); | ||
|
||
internal delegate void CFProxyAutoConfigurationResultCallback(IntPtr client, IntPtr proxyList, IntPtr error); | ||
|
||
[LibraryImport(Libraries.CFNetworkLibrary)] | ||
internal static partial CFRunLoopSourceRef CFNetworkExecuteProxyAutoConfigurationURL( | ||
IntPtr proxyAutoConfigURL, | ||
SafeCreateHandle targetURL, | ||
CFProxyAutoConfigurationResultCallback cb, | ||
ref CFStreamClientContext clientContext); | ||
|
||
[LibraryImport(Libraries.CFNetworkLibrary)] | ||
internal static partial 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 sealed 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; | ||
|
||
#pragma warning disable CA1810 // explicit static cctor | ||
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"); | ||
} | ||
} | ||
#pragma warning restore CA1810 | ||
|
||
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); | ||
} | ||
|
||
private static string LoadCFStringSymbol(IntPtr lib, string name) | ||
{ | ||
using (SafeCFStringHandle cfString = new SafeCFStringHandle(LoadSymbol(lib, name))) | ||
{ | ||
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)) | ||
{ | ||
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); | ||
unsafe | ||
{ | ||
int value; | ||
if (dictValue != IntPtr.Zero && CFNumberGetValue(dictValue, CFNumberType.kCFNumberIntType, &value) > 0) | ||
{ | ||
return value; | ||
} | ||
} | ||
return -1; | ||
} | ||
} | ||
|
||
public IntPtr AutoConfigurationURL => CFDictionaryGetValue(_dictionary, kCFProxyAutoConfigurationURLKey); | ||
public IntPtr AutoConfigurationJavaScript => CFDictionaryGetValue(_dictionary, kCFProxyAutoConfigurationJavaScriptKey); | ||
} | ||
} | ||
} |
Oops, something went wrong.