Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/java.base/macosx/native/libnet/DefaultProxySelector.c
67760 views
1
/*
2
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
3
* Copyright (c) 2017 SAP SE. All rights reserved.
4
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5
*
6
* This code is free software; you can redistribute it and/or modify it
7
* under the terms of the GNU General Public License version 2 only, as
8
* published by the Free Software Foundation. Oracle designates this
9
* particular file as subject to the "Classpath" exception as provided
10
* by Oracle in the LICENSE file that accompanied this code.
11
*
12
* This code is distributed in the hope that it will be useful, but WITHOUT
13
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15
* version 2 for more details (a copy is included in the LICENSE file that
16
* accompanied this code).
17
*
18
* You should have received a copy of the GNU General Public License version
19
* 2 along with this work; if not, write to the Free Software Foundation,
20
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21
*
22
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23
* or visit www.oracle.com if you need additional information or have any
24
* questions.
25
*/
26
27
#include <string.h>
28
#include <CoreFoundation/CoreFoundation.h>
29
#include <CoreServices/CoreServices.h>
30
#ifdef TARGET_OS_IOS
31
#include <CFNetwork/CFNetwork.h>
32
#endif
33
34
#include "jni.h"
35
#include "jni_util.h"
36
#include "jvm.h"
37
#include "jvm_md.h"
38
39
#include "proxy_util.h"
40
41
#include "sun_net_spi_DefaultProxySelector.h"
42
43
44
/**
45
* For more information on how to use the APIs in "CFProxySupport.h" see:
46
* https://developer.apple.com/legacy/library/samplecode/CFProxySupportTool/Introduction/Intro.html
47
*/
48
49
#define kResolveProxyRunLoopMode CFSTR("sun.net.spi.DefaultProxySelector")
50
51
#define BUFFER_SIZE 1024
52
53
/* Callback for CFNetworkExecuteProxyAutoConfigurationURL. */
54
static void proxyUrlCallback(void * client, CFArrayRef proxies, CFErrorRef error) {
55
/* client is a pointer to a CFTypeRef and holds either proxies or an error. */
56
CFTypeRef* resultPtr = (CFTypeRef *)client;
57
58
if (error != NULL) {
59
*resultPtr = CFRetain(error);
60
} else {
61
*resultPtr = CFRetain(proxies);
62
}
63
CFRunLoopStop(CFRunLoopGetCurrent());
64
}
65
66
/*
67
* Returns a new array of proxies containing all the given non-PAC proxies as
68
* well as the results of executing all the given PAC-based proxies, for the
69
* specified URL. 'proxies' is a list that may contain both PAC and non-PAC
70
* proxies.
71
*/
72
static CFArrayRef createExpandedProxiesArray(CFArrayRef proxies, CFURLRef url) {
73
74
CFIndex count;
75
CFIndex index;
76
CFMutableArrayRef expandedProxiesArray;
77
78
expandedProxiesArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
79
if (expandedProxiesArray == NULL)
80
return NULL;
81
82
/* Iterate over the array of proxies */
83
count = CFArrayGetCount(proxies);
84
for (index = 0; index < count ; index++) {
85
CFDictionaryRef currentProxy;
86
CFStringRef proxyType;
87
88
currentProxy = (CFDictionaryRef) CFArrayGetValueAtIndex(proxies, index);
89
if(currentProxy == NULL) {
90
CFRelease(expandedProxiesArray);
91
return NULL;
92
}
93
proxyType = (CFStringRef) CFDictionaryGetValue(currentProxy, kCFProxyTypeKey);
94
if (proxyType == NULL) {
95
CFRelease(expandedProxiesArray);
96
return NULL;
97
}
98
99
if (!CFEqual(proxyType, kCFProxyTypeAutoConfigurationURL)) {
100
/* Non-PAC entry, just copy it to the new array */
101
CFArrayAppendValue(expandedProxiesArray, currentProxy);
102
} else {
103
/* PAC-based URL, execute its script append its results */
104
CFRunLoopSourceRef runLoop;
105
CFURLRef scriptURL;
106
CFTypeRef result = NULL;
107
CFStreamClientContext context = { 0, &result, NULL, NULL, NULL };
108
CFTimeInterval timeout = 5;
109
110
scriptURL = CFDictionaryGetValue(currentProxy, kCFProxyAutoConfigurationURLKey);
111
112
runLoop = CFNetworkExecuteProxyAutoConfigurationURL(scriptURL, url, proxyUrlCallback,
113
&context);
114
if (runLoop != NULL) {
115
/*
116
* Despite the fact that CFNetworkExecuteProxyAutoConfigurationURL has
117
* neither a "Create" nor a "Copy" in the name, we are required to
118
* release the return CFRunLoopSourceRef <rdar://problem/5533931>.
119
*/
120
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoop, kResolveProxyRunLoopMode);
121
CFRunLoopRunInMode(kResolveProxyRunLoopMode, timeout, false);
122
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runLoop, kResolveProxyRunLoopMode);
123
124
/*
125
* Once the runloop returns, there will be either an error result or
126
* a proxies array result. Do the appropriate thing with that result.
127
*/
128
if (result != NULL) {
129
if (CFGetTypeID(result) == CFArrayGetTypeID()) {
130
/*
131
* Append the new array from the PAC list - it contains
132
* only non-PAC entries.
133
*/
134
CFArrayAppendArray(expandedProxiesArray, result,
135
CFRangeMake(0, CFArrayGetCount(result)));
136
}
137
CFRelease(result);
138
}
139
CFRelease(runLoop);
140
}
141
}
142
}
143
return expandedProxiesArray;
144
}
145
146
147
/*
148
* Class: sun_net_spi_DefaultProxySelector
149
* Method: init
150
* Signature: ()Z
151
*/
152
JNIEXPORT jboolean JNICALL
153
Java_sun_net_spi_DefaultProxySelector_init(JNIEnv *env, jclass clazz) {
154
if (!initJavaClass(env)) {
155
return JNI_FALSE;
156
}
157
return JNI_TRUE;
158
}
159
160
161
/*
162
* Class: sun_net_spi_DefaultProxySelector
163
* Method: getSystemProxies
164
* Signature: ([Ljava/lang/String;Ljava/lang/String;)[Ljava/net/Proxy;
165
*/
166
JNIEXPORT jobjectArray JNICALL
167
Java_sun_net_spi_DefaultProxySelector_getSystemProxies(JNIEnv *env,
168
jobject this,
169
jstring proto,
170
jstring host)
171
{
172
CFDictionaryRef proxyDicRef = NULL;
173
CFURLRef urlRef = NULL;
174
bool proxyFound = false;
175
jobjectArray proxyArray = NULL;
176
const char *cproto;
177
const char *chost;
178
179
/* Get system proxy settings */
180
proxyDicRef = CFNetworkCopySystemProxySettings();
181
if (proxyDicRef == NULL) {
182
return NULL;
183
}
184
185
/* Create CFURLRef from proto and host */
186
cproto = (*env)->GetStringUTFChars(env, proto, NULL);
187
if (cproto != NULL) {
188
chost = (*env)->GetStringUTFChars(env, host, NULL);
189
if (chost != NULL) {
190
char* uri = NULL;
191
size_t protoLen = 0;
192
size_t hostLen = 0;
193
194
protoLen = strlen(cproto);
195
hostLen = strlen(chost);
196
197
/* Construct the uri, cproto + "://" + chost */
198
uri = malloc(protoLen + hostLen + 4);
199
if (uri != NULL) {
200
memcpy(uri, cproto, protoLen);
201
memcpy(uri + protoLen, "://", 3);
202
memcpy(uri + protoLen + 3, chost, hostLen + 1);
203
204
urlRef = CFURLCreateWithBytes(NULL, (const UInt8 *) uri, strlen(uri),
205
kCFStringEncodingUTF8, NULL);
206
free(uri);
207
}
208
(*env)->ReleaseStringUTFChars(env, host, chost);
209
}
210
(*env)->ReleaseStringUTFChars(env, proto, cproto);
211
}
212
if (urlRef != NULL) {
213
CFArrayRef urlProxyArrayRef = CFNetworkCopyProxiesForURL(urlRef, proxyDicRef);
214
if (urlProxyArrayRef != NULL) {
215
CFIndex count;
216
CFIndex index;
217
218
CFArrayRef expandedProxyArray = createExpandedProxiesArray(urlProxyArrayRef, urlRef);
219
CFRelease(urlProxyArrayRef);
220
221
if (expandedProxyArray == NULL) {
222
CFRelease(urlRef);
223
CFRelease(proxyDicRef);
224
return NULL;
225
}
226
227
count = CFArrayGetCount(expandedProxyArray);
228
229
proxyArray = (*env)->NewObjectArray(env, count, proxy_class, NULL);
230
if (proxyArray != NULL || (*env)->ExceptionCheck(env)) {
231
/* Iterate over the expanded array of proxies */
232
for (index = 0; index < count ; index++) {
233
CFDictionaryRef currentProxy;
234
CFStringRef proxyType;
235
jobject proxy = NULL;
236
237
currentProxy = (CFDictionaryRef) CFArrayGetValueAtIndex(expandedProxyArray,
238
index);
239
proxyType = (CFStringRef) CFDictionaryGetValue(currentProxy, kCFProxyTypeKey);
240
if (CFEqual(proxyType, kCFProxyTypeNone)) {
241
/* This entry states no proxy, therefore just add a NO_PROXY object. */
242
proxy = (*env)->GetStaticObjectField(env, proxy_class, pr_no_proxyID);
243
} else {
244
/*
245
* Create a proxy object for this entry.
246
* Differentiate between SOCKS and HTTP type.
247
*/
248
jfieldID typeID = ptype_httpID;
249
if (CFEqual(proxyType, kCFProxyTypeSOCKS)) {
250
typeID = ptype_socksID;
251
}
252
CFNumberRef portNumberRef = (CFNumberRef)CFDictionaryGetValue(currentProxy,
253
(const void*)kCFProxyPortNumberKey);
254
if (portNumberRef != NULL) {
255
int port = 0;
256
if (CFNumberGetValue(portNumberRef, kCFNumberSInt32Type, &port)) {
257
CFStringRef hostNameRef = (CFStringRef)CFDictionaryGetValue(
258
currentProxy, (const void*)kCFProxyHostNameKey);
259
if (hostNameRef != NULL) {
260
char hostNameBuffer[BUFFER_SIZE];
261
if (CFStringGetCString(hostNameRef, hostNameBuffer,
262
BUFFER_SIZE, kCFStringEncodingUTF8)) {
263
proxy = createProxy(env, typeID, &hostNameBuffer[0], port);
264
}
265
}
266
}
267
}
268
}
269
if (proxy == NULL || (*env)->ExceptionCheck(env)) {
270
proxyArray = NULL;
271
break;
272
}
273
(*env)->SetObjectArrayElement(env, proxyArray, index, proxy);
274
if ((*env)->ExceptionCheck(env)) {
275
proxyArray = NULL;
276
break;
277
}
278
}
279
}
280
CFRelease(expandedProxyArray);
281
}
282
CFRelease(urlRef);
283
}
284
CFRelease(proxyDicRef);
285
286
return proxyArray;
287
}
288
289