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/classes/sun/net/sdp/SdpProvider.java
32288 views
1
/*
2
* Copyright (c) 2009, 2010, 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
package sun.net.sdp;
27
28
import sun.net.NetHooks;
29
import java.net.InetAddress;
30
import java.net.Inet4Address;
31
import java.net.UnknownHostException;
32
import java.util.*;
33
import java.io.File;
34
import java.io.FileDescriptor;
35
import java.io.IOException;
36
import java.io.PrintStream;
37
import java.security.AccessController;
38
39
import sun.net.sdp.SdpSupport;
40
import sun.security.action.GetPropertyAction;
41
42
/**
43
* A NetHooks provider that converts sockets from the TCP to SDP protocol prior
44
* to binding or connecting.
45
*/
46
47
public class SdpProvider extends NetHooks.Provider {
48
// maximum port
49
private static final int MAX_PORT = 65535;
50
51
// indicates if SDP is enabled and the rules for when the protocol is used
52
private final boolean enabled;
53
private final List<Rule> rules;
54
55
// logging for debug purposes
56
private PrintStream log;
57
58
public SdpProvider() {
59
// if this property is not defined then there is nothing to do.
60
String file = AccessController.doPrivileged(
61
new GetPropertyAction("com.sun.sdp.conf"));
62
if (file == null) {
63
this.enabled = false;
64
this.rules = null;
65
return;
66
}
67
68
// load configuration file
69
List<Rule> list = null;
70
if (file != null) {
71
try {
72
list = loadRulesFromFile(file);
73
} catch (IOException e) {
74
fail("Error reading %s: %s", file, e.getMessage());
75
}
76
}
77
78
// check if debugging is enabled
79
PrintStream out = null;
80
String logfile = AccessController.doPrivileged(
81
new GetPropertyAction("com.sun.sdp.debug"));
82
if (logfile != null) {
83
out = System.out;
84
if (logfile.length() > 0) {
85
try {
86
out = new PrintStream(logfile);
87
} catch (IOException ignore) { }
88
}
89
}
90
91
this.enabled = !list.isEmpty();
92
this.rules = list;
93
this.log = out;
94
}
95
96
// supported actions
97
private static enum Action {
98
BIND,
99
CONNECT;
100
}
101
102
// a rule for matching a bind or connect request
103
private static interface Rule {
104
boolean match(Action action, InetAddress address, int port);
105
}
106
107
// rule to match port[-end]
108
private static class PortRangeRule implements Rule {
109
private final Action action;
110
private final int portStart;
111
private final int portEnd;
112
PortRangeRule(Action action, int portStart, int portEnd) {
113
this.action = action;
114
this.portStart = portStart;
115
this.portEnd = portEnd;
116
}
117
Action action() {
118
return action;
119
}
120
@Override
121
public boolean match(Action action, InetAddress address, int port) {
122
return (action == this.action &&
123
port >= this.portStart &&
124
port <= this.portEnd);
125
}
126
}
127
128
// rule to match address[/prefix] port[-end]
129
private static class AddressPortRangeRule extends PortRangeRule {
130
private final byte[] addressAsBytes;
131
private final int prefixByteCount;
132
private final byte mask;
133
AddressPortRangeRule(Action action, InetAddress address,
134
int prefix, int port, int end)
135
{
136
super(action, port, end);
137
this.addressAsBytes = address.getAddress();
138
this.prefixByteCount = prefix >> 3;
139
this.mask = (byte)(0xff << (8 - (prefix % 8)));
140
}
141
@Override
142
public boolean match(Action action, InetAddress address, int port) {
143
if (action != action())
144
return false;
145
byte[] candidate = address.getAddress();
146
// same address type?
147
if (candidate.length != addressAsBytes.length)
148
return false;
149
// check bytes
150
for (int i=0; i<prefixByteCount; i++) {
151
if (candidate[i] != addressAsBytes[i])
152
return false;
153
}
154
// check remaining bits
155
if ((prefixByteCount < addressAsBytes.length) &&
156
((candidate[prefixByteCount] & mask) !=
157
(addressAsBytes[prefixByteCount] & mask)))
158
return false;
159
return super.match(action, address, port);
160
}
161
}
162
163
// parses port:[-end]
164
private static int[] parsePortRange(String s) {
165
int pos = s.indexOf('-');
166
try {
167
int[] result = new int[2];
168
if (pos < 0) {
169
boolean all = s.equals("*");
170
result[0] = all ? 0 : Integer.parseInt(s);
171
result[1] = all ? MAX_PORT : result[0];
172
} else {
173
String low = s.substring(0, pos);
174
if (low.length() == 0) low = "*";
175
String high = s.substring(pos+1);
176
if (high.length() == 0) high = "*";
177
result[0] = low.equals("*") ? 0 : Integer.parseInt(low);
178
result[1] = high.equals("*") ? MAX_PORT : Integer.parseInt(high);
179
}
180
return result;
181
} catch (NumberFormatException e) {
182
return new int[0];
183
}
184
}
185
186
private static void fail(String msg, Object... args) {
187
Formatter f = new Formatter();
188
f.format(msg, args);
189
throw new RuntimeException(f.out().toString());
190
}
191
192
// loads rules from the given file
193
// Each non-blank/non-comment line must have the format:
194
// ("bind" | "connect") 1*LWSP-char (hostname | ipaddress["/" prefix])
195
// 1*LWSP-char ("*" | port) [ "-" ("*" | port) ]
196
private static List<Rule> loadRulesFromFile(String file)
197
throws IOException
198
{
199
Scanner scanner = new Scanner(new File(file));
200
try {
201
List<Rule> result = new ArrayList<Rule>();
202
while (scanner.hasNextLine()) {
203
String line = scanner.nextLine().trim();
204
205
// skip blank lines and comments
206
if (line.length() == 0 || line.charAt(0) == '#')
207
continue;
208
209
// must have 3 fields
210
String[] s = line.split("\\s+");
211
if (s.length != 3) {
212
fail("Malformed line '%s'", line);
213
continue;
214
}
215
216
// first field is the action ("bind" or "connect")
217
Action action = null;
218
for (Action a: Action.values()) {
219
if (s[0].equalsIgnoreCase(a.name())) {
220
action = a;
221
break;
222
}
223
}
224
if (action == null) {
225
fail("Action '%s' not recognized", s[0]);
226
continue;
227
}
228
229
// * port[-end]
230
int[] ports = parsePortRange(s[2]);
231
if (ports.length == 0) {
232
fail("Malformed port range '%s'", s[2]);
233
continue;
234
}
235
236
// match all addresses
237
if (s[1].equals("*")) {
238
result.add(new PortRangeRule(action, ports[0], ports[1]));
239
continue;
240
}
241
242
// hostname | ipaddress[/prefix]
243
int pos = s[1].indexOf('/');
244
try {
245
if (pos < 0) {
246
// hostname or ipaddress (no prefix)
247
InetAddress[] addresses = InetAddress.getAllByName(s[1]);
248
for (InetAddress address: addresses) {
249
int prefix =
250
(address instanceof Inet4Address) ? 32 : 128;
251
result.add(new AddressPortRangeRule(action, address,
252
prefix, ports[0], ports[1]));
253
}
254
} else {
255
// ipaddress/prefix
256
InetAddress address = InetAddress
257
.getByName(s[1].substring(0, pos));
258
int prefix = -1;
259
try {
260
prefix = Integer.parseInt(s[1].substring(pos+1));
261
if (address instanceof Inet4Address) {
262
// must be 1-31
263
if (prefix < 0 || prefix > 32) prefix = -1;
264
} else {
265
// must be 1-128
266
if (prefix < 0 || prefix > 128) prefix = -1;
267
}
268
} catch (NumberFormatException e) {
269
}
270
271
if (prefix > 0) {
272
result.add(new AddressPortRangeRule(action,
273
address, prefix, ports[0], ports[1]));
274
} else {
275
fail("Malformed prefix '%s'", s[1]);
276
continue;
277
}
278
}
279
} catch (UnknownHostException uhe) {
280
fail("Unknown host or malformed IP address '%s'", s[1]);
281
continue;
282
}
283
}
284
return result;
285
} finally {
286
scanner.close();
287
}
288
}
289
290
// converts unbound TCP socket to a SDP socket if it matches the rules
291
private void convertTcpToSdpIfMatch(FileDescriptor fdObj,
292
Action action,
293
InetAddress address,
294
int port)
295
throws IOException
296
{
297
boolean matched = false;
298
for (Rule rule: rules) {
299
if (rule.match(action, address, port)) {
300
SdpSupport.convertSocket(fdObj);
301
matched = true;
302
break;
303
}
304
}
305
if (log != null) {
306
String addr = (address instanceof Inet4Address) ?
307
address.getHostAddress() : "[" + address.getHostAddress() + "]";
308
if (matched) {
309
log.format("%s to %s:%d (socket converted to SDP protocol)\n", action, addr, port);
310
} else {
311
log.format("%s to %s:%d (no match)\n", action, addr, port);
312
}
313
}
314
}
315
316
@Override
317
public void implBeforeTcpBind(FileDescriptor fdObj,
318
InetAddress address,
319
int port)
320
throws IOException
321
{
322
if (enabled)
323
convertTcpToSdpIfMatch(fdObj, Action.BIND, address, port);
324
}
325
326
@Override
327
public void implBeforeTcpConnect(FileDescriptor fdObj,
328
InetAddress address,
329
int port)
330
throws IOException
331
{
332
if (enabled)
333
convertTcpToSdpIfMatch(fdObj, Action.CONNECT, address, port);
334
}
335
}
336
337