Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/sun/net/spi/DefaultProxySelector.c
32288 views
1
/*
2
* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
#include "jni.h"
27
#include "jni_util.h"
28
#include "jvm.h"
29
#include "jvm_md.h"
30
#include "jlong.h"
31
#include "sun_net_spi_DefaultProxySelector.h"
32
#include <dlfcn.h>
33
#include <stdio.h>
34
#include <stdlib.h>
35
#if defined(__linux__) || defined(_ALLBSD_SOURCE)
36
#include <string.h>
37
#else
38
#include <strings.h>
39
#endif
40
41
/**
42
* These functions are used by the sun.net.spi.DefaultProxySelector class
43
* to access some platform specific settings.
44
* This is the Solaris/Linux Gnome 2.x code using the GConf-2 library.
45
* Everything is loaded dynamically so no hard link with any library exists.
46
* The GConf-2 settings used are:
47
* - /system/http_proxy/use_http_proxy boolean
48
* - /system/http_proxy/use_authentcation boolean
49
* - /system/http_proxy/use_same_proxy boolean
50
* - /system/http_proxy/host string
51
* - /system/http_proxy/authentication_user string
52
* - /system/http_proxy/authentication_password string
53
* - /system/http_proxy/port int
54
* - /system/proxy/socks_host string
55
* - /system/proxy/mode string
56
* - /system/proxy/ftp_host string
57
* - /system/proxy/secure_host string
58
* - /system/proxy/socks_port int
59
* - /system/proxy/ftp_port int
60
* - /system/proxy/secure_port int
61
* - /system/proxy/no_proxy_for list
62
* - /system/proxy/gopher_host string
63
* - /system/proxy/gopher_port int
64
*
65
* The following keys are not used in the new gnome 3
66
* - /system/http_proxy/use_http_proxy
67
* - /system/http_proxy/use_same_proxy
68
*/
69
typedef void* gconf_client_get_default_func();
70
typedef char* gconf_client_get_string_func(void *, char *, void**);
71
typedef int gconf_client_get_int_func(void*, char *, void**);
72
typedef int gconf_client_get_bool_func(void*, char *, void**);
73
typedef int gconf_init_func(int, char**, void**);
74
typedef void g_type_init_func ();
75
gconf_client_get_default_func* my_get_default_func = NULL;
76
gconf_client_get_string_func* my_get_string_func = NULL;
77
gconf_client_get_int_func* my_get_int_func = NULL;
78
gconf_client_get_bool_func* my_get_bool_func = NULL;
79
gconf_init_func* my_gconf_init_func = NULL;
80
g_type_init_func* my_g_type_init_func = NULL;
81
82
83
/*
84
* GProxyResolver provides synchronous and asynchronous network
85
* proxy resolution. It is based on GSettings, which is the standard
86
* of Gnome 3, to get system settings.
87
*
88
* In the current implementation, GProxyResolver has a higher priority
89
* than the old GConf. And we only resolve the proxy synchronously. In
90
* the future, we can also do the asynchronous network proxy resolution
91
* if necessary.
92
*
93
*/
94
typedef struct _GProxyResolver GProxyResolver;
95
typedef struct _GSocketConnectable GSocketConnectable;
96
typedef struct GError GError;
97
typedef GProxyResolver* g_proxy_resolver_get_default_func();
98
typedef char** g_proxy_resolver_lookup_func();
99
typedef GSocketConnectable* g_network_address_parse_uri_func();
100
typedef const char* g_network_address_get_hostname_func();
101
typedef unsigned short g_network_address_get_port_func();
102
typedef void g_strfreev_func();
103
104
static g_proxy_resolver_get_default_func* g_proxy_resolver_get_default = NULL;
105
static g_proxy_resolver_lookup_func* g_proxy_resolver_lookup = NULL;
106
static g_network_address_parse_uri_func* g_network_address_parse_uri = NULL;
107
static g_network_address_get_hostname_func* g_network_address_get_hostname = NULL;
108
static g_network_address_get_port_func* g_network_address_get_port = NULL;
109
static g_strfreev_func* g_strfreev = NULL;
110
111
112
static jclass proxy_class;
113
static jclass isaddr_class;
114
static jclass ptype_class;
115
static jmethodID isaddr_createUnresolvedID;
116
static jmethodID proxy_ctrID;
117
static jfieldID pr_no_proxyID;
118
static jfieldID ptype_httpID;
119
static jfieldID ptype_socksID;
120
121
122
static void* gconf_client = NULL;
123
124
static int use_gproxyResolver = 0;
125
static int use_gconf = 0;
126
127
#define CHECK_NULL(X) { if ((X) == NULL) fprintf (stderr,"JNI errror at line %d\n", __LINE__); }
128
129
130
static int initGConf() {
131
/**
132
* Let's try to load GConf-2 library
133
*/
134
if (dlopen(JNI_LIB_NAME("gconf-2"), RTLD_GLOBAL | RTLD_LAZY) != NULL ||
135
dlopen(VERSIONED_JNI_LIB_NAME("gconf-2", "4"),
136
RTLD_GLOBAL | RTLD_LAZY) != NULL)
137
{
138
/*
139
* Now let's get pointer to the functions we need.
140
*/
141
my_g_type_init_func =
142
(g_type_init_func*)dlsym(RTLD_DEFAULT, "g_type_init");
143
my_get_default_func =
144
(gconf_client_get_default_func*)dlsym(RTLD_DEFAULT,
145
"gconf_client_get_default");
146
147
if (my_g_type_init_func != NULL && my_get_default_func != NULL) {
148
/**
149
* Try to connect to GConf.
150
*/
151
(*my_g_type_init_func)();
152
gconf_client = (*my_get_default_func)();
153
if (gconf_client != NULL) {
154
my_get_string_func =
155
(gconf_client_get_string_func*)dlsym(RTLD_DEFAULT,
156
"gconf_client_get_string");
157
my_get_int_func =
158
(gconf_client_get_int_func*)dlsym(RTLD_DEFAULT,
159
"gconf_client_get_int");
160
my_get_bool_func =
161
(gconf_client_get_bool_func*)dlsym(RTLD_DEFAULT,
162
"gconf_client_get_bool");
163
if (my_get_int_func != NULL && my_get_string_func != NULL &&
164
my_get_bool_func != NULL)
165
{
166
/**
167
* We did get all we need. Let's enable the System Proxy Settings.
168
*/
169
return 1;
170
}
171
}
172
}
173
}
174
return 0;
175
}
176
177
static jobject getProxyByGConf(JNIEnv *env, const char* cproto,
178
const char* chost)
179
{
180
char *phost = NULL;
181
char *mode = NULL;
182
int pport = 0;
183
int use_proxy = 0;
184
int use_same_proxy = 0;
185
jobject isa = NULL;
186
jobject proxy = NULL;
187
jobject type_proxy = NULL;
188
189
// We only check manual proxy configurations
190
mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL);
191
if (mode && !strcasecmp(mode, "manual")) {
192
/*
193
* Even though /system/http_proxy/use_same_proxy is no longer used,
194
* its value is set to false in gnome 3. So it is not harmful to check
195
* it first in case jdk is used with an old gnome.
196
*/
197
use_same_proxy = (*my_get_bool_func)(gconf_client, "/system/http_proxy/use_same_proxy", NULL);
198
if (use_same_proxy) {
199
phost = (*my_get_string_func)(gconf_client, "/system/http_proxy/host", NULL);
200
pport = (*my_get_int_func)(gconf_client, "/system/http_proxy/port", NULL);
201
use_proxy = (phost != NULL && pport != 0);
202
if (use_proxy)
203
type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
204
}
205
206
if (!use_proxy) {
207
/**
208
* HTTP:
209
* /system/http_proxy/use_http_proxy (boolean) - it's no longer used
210
* /system/http_proxy/host (string)
211
* /system/http_proxy/port (integer)
212
*/
213
if (strcasecmp(cproto, "http") == 0) {
214
phost = (*my_get_string_func)(gconf_client, "/system/http_proxy/host", NULL);
215
pport = (*my_get_int_func)(gconf_client, "/system/http_proxy/port", NULL);
216
use_proxy = (phost != NULL && pport != 0);
217
if (use_proxy)
218
type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
219
}
220
221
/**
222
* HTTPS:
223
* /system/proxy/mode (string) [ "manual" means use proxy settings ]
224
* /system/proxy/secure_host (string)
225
* /system/proxy/secure_port (integer)
226
*/
227
if (strcasecmp(cproto, "https") == 0) {
228
phost = (*my_get_string_func)(gconf_client, "/system/proxy/secure_host", NULL);
229
pport = (*my_get_int_func)(gconf_client, "/system/proxy/secure_port", NULL);
230
use_proxy = (phost != NULL && pport != 0);
231
if (use_proxy)
232
type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
233
}
234
235
/**
236
* FTP:
237
* /system/proxy/mode (string) [ "manual" means use proxy settings ]
238
* /system/proxy/ftp_host (string)
239
* /system/proxy/ftp_port (integer)
240
*/
241
if (strcasecmp(cproto, "ftp") == 0) {
242
phost = (*my_get_string_func)(gconf_client, "/system/proxy/ftp_host", NULL);
243
pport = (*my_get_int_func)(gconf_client, "/system/proxy/ftp_port", NULL);
244
use_proxy = (phost != NULL && pport != 0);
245
if (use_proxy)
246
type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
247
}
248
249
/**
250
* GOPHER:
251
* /system/proxy/mode (string) [ "manual" means use proxy settings ]
252
* /system/proxy/gopher_host (string)
253
* /system/proxy/gopher_port (integer)
254
*/
255
if (strcasecmp(cproto, "gopher") == 0) {
256
phost = (*my_get_string_func)(gconf_client, "/system/proxy/gopher_host", NULL);
257
pport = (*my_get_int_func)(gconf_client, "/system/proxy/gopher_port", NULL);
258
use_proxy = (phost != NULL && pport != 0);
259
if (use_proxy)
260
type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
261
}
262
263
/**
264
* SOCKS:
265
* /system/proxy/mode (string) [ "manual" means use proxy settings ]
266
* /system/proxy/socks_host (string)
267
* /system/proxy/socks_port (integer)
268
*/
269
if (strcasecmp(cproto, "socks") == 0) {
270
phost = (*my_get_string_func)(gconf_client, "/system/proxy/socks_host", NULL);
271
pport = (*my_get_int_func)(gconf_client, "/system/proxy/socks_port", NULL);
272
use_proxy = (phost != NULL && pport != 0);
273
if (use_proxy)
274
type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_socksID);
275
}
276
}
277
}
278
279
if (use_proxy) {
280
jstring jhost;
281
char *noproxyfor;
282
char *s;
283
284
/**
285
* check for the exclude list (aka "No Proxy For" list).
286
* It's a list of comma separated suffixes (e.g. domain name).
287
*/
288
noproxyfor = (*my_get_string_func)(gconf_client, "/system/proxy/no_proxy_for", NULL);
289
if (noproxyfor != NULL) {
290
char *tmpbuf[512];
291
s = strtok_r(noproxyfor, ", ", tmpbuf);
292
293
while (s != NULL && strlen(s) <= strlen(chost)) {
294
if (strcasecmp(chost+(strlen(chost) - strlen(s)), s) == 0) {
295
/**
296
* the URL host name matches with one of the sufixes,
297
* therefore we have to use a direct connection.
298
*/
299
use_proxy = 0;
300
break;
301
}
302
s = strtok_r(NULL, ", ", tmpbuf);
303
}
304
}
305
if (use_proxy) {
306
CHECK_NULL(type_proxy);
307
jhost = (*env)->NewStringUTF(env, phost);
308
isa = (*env)->CallStaticObjectMethod(env, isaddr_class, isaddr_createUnresolvedID, jhost, pport);
309
proxy = (*env)->NewObject(env, proxy_class, proxy_ctrID, type_proxy, isa);
310
}
311
}
312
313
return proxy;
314
}
315
316
static int initGProxyResolver() {
317
void *gio_handle;
318
319
gio_handle = dlopen("libgio-2.0.so", RTLD_LAZY);
320
if (!gio_handle) {
321
gio_handle = dlopen("libgio-2.0.so.0", RTLD_LAZY);
322
if (!gio_handle) {
323
return 0;
324
}
325
}
326
327
my_g_type_init_func = (g_type_init_func*)dlsym(gio_handle, "g_type_init");
328
329
g_proxy_resolver_get_default =
330
(g_proxy_resolver_get_default_func*)dlsym(gio_handle,
331
"g_proxy_resolver_get_default");
332
333
g_proxy_resolver_lookup =
334
(g_proxy_resolver_lookup_func*)dlsym(gio_handle,
335
"g_proxy_resolver_lookup");
336
337
g_network_address_parse_uri =
338
(g_network_address_parse_uri_func*)dlsym(gio_handle,
339
"g_network_address_parse_uri");
340
341
g_network_address_get_hostname =
342
(g_network_address_get_hostname_func*)dlsym(gio_handle,
343
"g_network_address_get_hostname");
344
345
g_network_address_get_port =
346
(g_network_address_get_port_func*)dlsym(gio_handle,
347
"g_network_address_get_port");
348
349
g_strfreev = (g_strfreev_func*)dlsym(gio_handle, "g_strfreev");
350
351
if (!my_g_type_init_func ||
352
!g_proxy_resolver_get_default ||
353
!g_proxy_resolver_lookup ||
354
!g_network_address_parse_uri ||
355
!g_network_address_get_hostname ||
356
!g_network_address_get_port ||
357
!g_strfreev)
358
{
359
dlclose(gio_handle);
360
return 0;
361
}
362
363
(*my_g_type_init_func)();
364
return 1;
365
}
366
367
static jobject getProxyByGProxyResolver(JNIEnv *env, const char* cproto,
368
const char* chost)
369
{
370
GProxyResolver* resolver = NULL;
371
char** proxies = NULL;
372
GError *error = NULL;
373
374
size_t protoLen = 0;
375
size_t hostLen = 0;
376
char* uri = NULL;
377
378
jobject objProxy = NULL;
379
380
resolver = (*g_proxy_resolver_get_default)();
381
if (resolver == NULL) {
382
return NULL;
383
}
384
385
// Construct the uri, cproto + "://" + chost
386
protoLen = strlen(cproto);
387
hostLen = strlen(chost);
388
uri = malloc(protoLen + hostLen + 4);
389
if (!uri) {
390
// Out of memory
391
return NULL;
392
}
393
memcpy(uri, cproto, protoLen);
394
memcpy(uri + protoLen, "://", 3);
395
memcpy(uri + protoLen + 3, chost, hostLen + 1);
396
397
/*
398
* Looks into the system proxy configuration to determine what proxy,
399
* if any, to use to connect to uri. The returned proxy URIs are of
400
* the form <protocol>://[user[:password]@]host:port or direct://,
401
* where <protocol> could be http, rtsp, socks or other proxying protocol.
402
* direct:// is used when no proxy is needed.
403
*/
404
proxies = (*g_proxy_resolver_lookup)(resolver, uri, NULL, &error);
405
free(uri);
406
407
if (proxies) {
408
if (!error) {
409
int i;
410
for(i = 0; proxies[i] && !objProxy; i++) {
411
if (strcmp(proxies[i], "direct://")) {
412
GSocketConnectable* conn =
413
(*g_network_address_parse_uri)(proxies[i], 0,
414
&error);
415
if (conn && !error) {
416
const char* phost = NULL;
417
unsigned short pport = 0;
418
phost = (*g_network_address_get_hostname)(conn);
419
pport = (*g_network_address_get_port)(conn);
420
if (phost && pport > 0) {
421
jobject type_proxy = NULL;
422
jstring jhost = NULL;
423
jobject isa = NULL;
424
jfieldID ptype_ID = ptype_httpID;
425
if (!strncmp(proxies[i], "socks", 5)) {
426
ptype_ID = ptype_socksID;
427
}
428
429
type_proxy = (*env)->GetStaticObjectField(env,
430
ptype_class, ptype_ID);
431
CHECK_NULL(type_proxy);
432
jhost = (*env)->NewStringUTF(env, phost);
433
CHECK_NULL(jhost);
434
isa = (*env)->CallStaticObjectMethod(env,
435
isaddr_class, isaddr_createUnresolvedID,
436
jhost, pport);
437
CHECK_NULL(isa);
438
objProxy = (*env)->NewObject(env, proxy_class,
439
proxy_ctrID, type_proxy, isa);
440
}
441
}
442
}
443
}
444
}
445
(*g_strfreev)(proxies);
446
}
447
448
return objProxy;
449
}
450
451
static void initJavaClass(JNIEnv *env) {
452
jclass cls = NULL;
453
CHECK_NULL(cls = (*env)->FindClass(env,"java/net/Proxy"));
454
proxy_class = (*env)->NewGlobalRef(env, cls);
455
CHECK_NULL(cls = (*env)->FindClass(env,"java/net/Proxy$Type"));
456
ptype_class = (*env)->NewGlobalRef(env, cls);
457
CHECK_NULL(cls = (*env)->FindClass(env, "java/net/InetSocketAddress"));
458
isaddr_class = (*env)->NewGlobalRef(env, cls);
459
proxy_ctrID = (*env)->GetMethodID(env, proxy_class, "<init>",
460
"(Ljava/net/Proxy$Type;Ljava/net/SocketAddress;)V");
461
CHECK_NULL(proxy_ctrID);
462
pr_no_proxyID = (*env)->GetStaticFieldID(env, proxy_class, "NO_PROXY",
463
"Ljava/net/Proxy;");
464
CHECK_NULL(pr_no_proxyID);
465
ptype_httpID = (*env)->GetStaticFieldID(env, ptype_class, "HTTP",
466
"Ljava/net/Proxy$Type;");
467
CHECK_NULL(ptype_httpID);
468
ptype_socksID = (*env)->GetStaticFieldID(env, ptype_class, "SOCKS",
469
"Ljava/net/Proxy$Type;");
470
CHECK_NULL(ptype_socksID);
471
isaddr_createUnresolvedID = (*env)->GetStaticMethodID(env, isaddr_class,
472
"createUnresolved",
473
"(Ljava/lang/String;I)Ljava/net/InetSocketAddress;");
474
CHECK_NULL(isaddr_createUnresolvedID);
475
}
476
477
478
/*
479
* Class: sun_net_spi_DefaultProxySelector
480
* Method: init
481
* Signature: ()Z
482
*/
483
JNIEXPORT jboolean JNICALL
484
Java_sun_net_spi_DefaultProxySelector_init(JNIEnv *env, jclass clazz) {
485
use_gproxyResolver = initGProxyResolver();
486
if (!use_gproxyResolver)
487
use_gconf = initGConf();
488
489
if (use_gproxyResolver || use_gconf) {
490
initJavaClass(env);
491
return JNI_TRUE;
492
} else
493
return JNI_FALSE;
494
}
495
496
/*
497
* Class: sun_net_spi_DefaultProxySelector
498
* Method: getSystemProxy
499
* Signature: ([Ljava/lang/String;Ljava/lang/String;)Ljava/net/Proxy;
500
*/
501
JNIEXPORT jobject JNICALL
502
Java_sun_net_spi_DefaultProxySelector_getSystemProxy(JNIEnv *env,
503
jobject this,
504
jstring proto,
505
jstring host)
506
{
507
const char* cproto;
508
const char* chost;
509
510
jboolean isProtoCopy;
511
jboolean isHostCopy;
512
513
jobject proxy = NULL;
514
515
cproto = (*env)->GetStringUTFChars(env, proto, &isProtoCopy);
516
517
if (cproto != NULL && (use_gproxyResolver || use_gconf)) {
518
chost = (*env)->GetStringUTFChars(env, host, &isHostCopy);
519
if (chost != NULL) {
520
if (use_gproxyResolver)
521
proxy = getProxyByGProxyResolver(env, cproto, chost);
522
else if (use_gconf)
523
proxy = getProxyByGConf(env, cproto, chost);
524
525
if (isHostCopy == JNI_TRUE)
526
(*env)->ReleaseStringUTFChars(env, host, chost);
527
}
528
if (isProtoCopy == JNI_TRUE)
529
(*env)->ReleaseStringUTFChars(env, proto, cproto);
530
}
531
532
if (proxy == NULL) {
533
CHECK_NULL(proxy = (*env)->GetStaticObjectField(env, proxy_class,
534
pr_no_proxyID));
535
}
536
return proxy;
537
}
538
539
540