-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathSwiftFlutterSystemProxyPlugin.swift
More file actions
120 lines (110 loc) · 5.36 KB
/
SwiftFlutterSystemProxyPlugin.swift
File metadata and controls
120 lines (110 loc) · 5.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import Flutter
import UIKit
import JavaScriptCore
public class SwiftFlutterSystemProxyPlugin: NSObject, FlutterPlugin {
static var proxyCache : [String: [String: Any]] = [:]
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: "flutter_system_proxy", binaryMessenger: registrar.messenger())
let instance = SwiftFlutterSystemProxyPlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "getDeviceProxy":
let args = call.arguments as! NSDictionary
let url = args.value(forKey:"url") as! String
var dict:[String:Any]? = [:]
if(SwiftFlutterSystemProxyPlugin.proxyCache[url] != nil){
let res = SwiftFlutterSystemProxyPlugin.proxyCache[url]
if(res != nil){
dict = res
}
}
else
{
let res = SwiftFlutterSystemProxyPlugin.resolve(url: url)
if(res != nil){
dict = res
}
}
result(dict)
break
default:
result(FlutterMethodNotImplemented)
}
}
static func resolve(url:String)->[String:Any]?{
if(SwiftFlutterSystemProxyPlugin.proxyCache[url] != nil){
return SwiftFlutterSystemProxyPlugin.proxyCache[url]
}
let proxConfigDict = CFNetworkCopySystemProxySettings()?.takeUnretainedValue() as NSDictionary?
if proxConfigDict != nil {
if(proxConfigDict?[kCFNetworkProxiesProxyAutoConfigEnable] as? Int == 1){
let pacUrl = proxConfigDict?[kCFNetworkProxiesProxyAutoConfigURLString] as! String?
let pacContent = proxConfigDict?[kCFNetworkProxiesProxyAutoConfigJavaScript] as! String?
if(pacContent != nil){
self.handlePacContent(pacContent: pacContent!, url: url)
}else if(pacUrl != nil){
self.handlePacUrl(pacUrl: pacUrl!,url: url)
}
} else if (proxConfigDict![kCFNetworkProxiesHTTPEnable] as? Int == 1){
var dict: [String: Any] = [:]
dict["host"] = proxConfigDict![kCFNetworkProxiesHTTPProxy] as? String
dict["port"] = proxConfigDict![kCFNetworkProxiesHTTPPort] as? Int
SwiftFlutterSystemProxyPlugin.proxyCache[url] = dict
}
}
return SwiftFlutterSystemProxyPlugin.proxyCache[url]
}
static func handlePacContent(pacContent: String,url: String){
let proxies = CFNetworkCopyProxiesForAutoConfigurationScript(pacContent as CFString, CFURLCreateWithString(kCFAllocatorDefault, url as CFString, nil), nil)!.takeUnretainedValue() as? [[CFString: Any]] ?? [];
if(proxies.count > 0){
let proxy = proxies.first{$0[kCFProxyTypeKey] as! CFString == kCFProxyTypeHTTP || $0[kCFProxyTypeKey] as! CFString == kCFProxyTypeHTTPS}
if(proxy != nil){
let host = proxy?[kCFProxyHostNameKey] ?? nil
let port = proxy?[kCFProxyPortNumberKey] ?? nil
var dict:[String: Any] = [:]
dict["host"] = host
dict["port"] = port
SwiftFlutterSystemProxyPlugin.proxyCache[url] = dict
}
}
}
static func handlePacUrl(pacUrl: String, url: String) {
let _pacUrl = CFURLCreateWithString(kCFAllocatorDefault, pacUrl as CFString?, nil)
let targetUrl = CFURLCreateWithString(kCFAllocatorDefault, url as CFString?, nil)
var info = url
withUnsafeMutablePointer(to: &info, { infoPointer in
var context: CFStreamClientContext = CFStreamClientContext(version: 0, info: infoPointer, retain: nil, release: nil, copyDescription: nil)
let unmanagedRunLoopSource = CFNetworkExecuteProxyAutoConfigurationURL(_pacUrl!, targetUrl!, { client, proxies, error in
let _proxies = proxies as? [[CFString: Any]] ?? []
if (_proxies.count > 0) {
let proxy = _proxies.first { $0[kCFProxyTypeKey] as! CFString == kCFProxyTypeHTTP || $0[kCFProxyTypeKey] as! CFString == kCFProxyTypeHTTPS }
if (proxy != nil) {
let host = proxy?[kCFProxyHostNameKey] ?? nil
let port = proxy?[kCFProxyPortNumberKey] ?? nil
var dict: [String: Any] = [:]
dict["host"] = host
dict["port"] = port
let url = client.assumingMemoryBound(to: String.self).pointee
SwiftFlutterSystemProxyPlugin.proxyCache[url] = dict
}
}
CFRunLoopStop(CFRunLoopGetCurrent())
}, &context)
let runLoopSource = unmanagedRunLoopSource.takeUnretainedValue()
let runLoop = CFRunLoopGetCurrent()
CFRunLoopAddSource(runLoop, runLoopSource, CFRunLoopMode.defaultMode)
CFRunLoopRun()
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runLoopSource, CFRunLoopMode.defaultMode)
})
}
//For backward compatibility <= XCode 15
static func getRunLoopSource<T>(_ runLoopSource: T) -> CFRunLoopSource {
if let unmanagedValue = runLoopSource as? Unmanaged<CFRunLoopSource> {
return unmanagedValue.takeUnretainedValue()
} else {
return runLoopSource as! CFRunLoopSource
}
}
}