using CPF.Mac.CoreFoundation; using CPF.Mac.Foundation; using CPF.Mac.ObjCRuntime; using System; namespace CPF.Mac.CoreServices { public class CFHTTPStream : CFReadStream { private static readonly NSString _AttemptPersistentConnection; private static readonly NSString _FinalURL; private static readonly NSString _FinalRequest; private static readonly NSString _Proxy; private static readonly NSString _RequestBytesWrittenCount; private static readonly NSString _ResponseHeader; private static readonly NSString _ShouldAutoredirect; public CFUrl FinalURL { get { IntPtr property = GetProperty(_FinalURL); if (property == IntPtr.Zero) { return null; } if (CFType.GetTypeID(property) != CFUrl.GetTypeID()) { CFObject.CFRelease(property); throw new InvalidCastException(); } return new CFUrl(property); } } public bool AttemptPersistentConnection { get { IntPtr property = GetProperty(_AttemptPersistentConnection); if (property == IntPtr.Zero) { return false; } if (property == CFBoolean.False.Handle) { return false; } if (property == CFBoolean.True.Handle) { return true; } throw new InvalidCastException(); } set { SetProperty(_AttemptPersistentConnection, CFBoolean.FromBoolean(value)); } } public int RequestBytesWrittenCount { get { IntPtr property = GetProperty(_RequestBytesWrittenCount); if (property == IntPtr.Zero) { return 0; } using (NSNumber nSNumber = new NSNumber(property)) { return nSNumber.Int32Value; } } } public bool ShouldAutoredirect { get { IntPtr property = GetProperty(_ShouldAutoredirect); if (property == IntPtr.Zero) { return false; } if (property == CFBoolean.False.Handle) { return false; } if (property == CFBoolean.True.Handle) { return true; } throw new InvalidCastException(); } set { SetProperty(_ShouldAutoredirect, CFBoolean.FromBoolean(value)); } } internal CFDictionary Proxy { set { SetProperty(_Proxy, value); } } static CFHTTPStream() { IntPtr intPtr = Dlfcn.dlopen("/System/Library/Frameworks/CoreServices.framework/Frameworks/CFNetwork.framework/CFNetwork", 0); if (intPtr == IntPtr.Zero) { throw new InvalidOperationException(); } try { _AttemptPersistentConnection = GetStringConstant(intPtr, "kCFStreamPropertyHTTPAttemptPersistentConnection"); _FinalURL = GetStringConstant(intPtr, "kCFStreamPropertyHTTPFinalURL"); _FinalRequest = GetStringConstant(intPtr, "kCFStreamPropertyHTTPFinalRequest"); _Proxy = GetStringConstant(intPtr, "kCFStreamPropertyHTTPProxy"); _RequestBytesWrittenCount = GetStringConstant(intPtr, "kCFStreamPropertyHTTPRequestBytesWrittenCount"); _ResponseHeader = GetStringConstant(intPtr, "kCFStreamPropertyHTTPResponseHeader"); _ShouldAutoredirect = GetStringConstant(intPtr, "kCFStreamPropertyHTTPShouldAutoredirect"); } finally { Dlfcn.dlclose(intPtr); } } private static NSString GetStringConstant(IntPtr handle, string name) { NSString stringConstant = Dlfcn.GetStringConstant(handle, name); if (stringConstant == null) { throw new InvalidOperationException($"Cannot get '{name}' property."); } return stringConstant; } internal CFHTTPStream(IntPtr handle) : base(handle) { } public CFHTTPMessage GetFinalRequest() { IntPtr property = GetProperty(_FinalRequest); if (property == IntPtr.Zero) { return null; } if (CFType.GetTypeID(property) != CFHTTPMessage.GetTypeID()) { CFObject.CFRelease(property); throw new InvalidCastException(); } return new CFHTTPMessage(property); } public CFHTTPMessage GetResponseHeader() { IntPtr property = GetProperty(_ResponseHeader); if (property == IntPtr.Zero) { return null; } if (CFType.GetTypeID(property) != CFHTTPMessage.GetTypeID()) { CFObject.CFRelease(property); throw new InvalidCastException(); } return new CFHTTPMessage(property); } } }