Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java
38829 views
1
/*
2
* Copyright (c) 1995, 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
package java.net;
27
28
import java.io.IOException;
29
import java.io.InputStream;
30
import java.io.OutputStream;
31
import java.io.FileDescriptor;
32
33
import sun.net.ConnectionResetException;
34
import sun.net.NetHooks;
35
import sun.net.ResourceManager;
36
37
/**
38
* Default Socket Implementation. This implementation does
39
* not implement any security checks.
40
* Note this class should <b>NOT</b> be public.
41
*
42
* @author Steven B. Byrne
43
*/
44
abstract class AbstractPlainSocketImpl extends SocketImpl
45
{
46
/* instance variable for SO_TIMEOUT */
47
int timeout; // timeout in millisec
48
// traffic class
49
private int trafficClass;
50
51
private boolean shut_rd = false;
52
private boolean shut_wr = false;
53
54
private SocketInputStream socketInputStream = null;
55
private SocketOutputStream socketOutputStream = null;
56
57
/* number of threads using the FileDescriptor */
58
protected int fdUseCount = 0;
59
60
/* lock when increment/decrementing fdUseCount */
61
protected final Object fdLock = new Object();
62
63
/* indicates a close is pending on the file descriptor */
64
protected boolean closePending = false;
65
66
/* indicates connection reset state */
67
private int CONNECTION_NOT_RESET = 0;
68
private int CONNECTION_RESET_PENDING = 1;
69
private int CONNECTION_RESET = 2;
70
private int resetState;
71
private final Object resetLock = new Object();
72
73
/* whether this Socket is a stream (TCP) socket or not (UDP)
74
*/
75
protected boolean stream;
76
77
/**
78
* Load net library into runtime.
79
*/
80
static {
81
java.security.AccessController.doPrivileged(
82
new java.security.PrivilegedAction<Void>() {
83
public Void run() {
84
System.loadLibrary("net");
85
return null;
86
}
87
});
88
}
89
90
/**
91
* Creates a socket with a boolean that specifies whether this
92
* is a stream socket (true) or an unconnected UDP socket (false).
93
*/
94
protected synchronized void create(boolean stream) throws IOException {
95
this.stream = stream;
96
if (!stream) {
97
ResourceManager.beforeUdpCreate();
98
// only create the fd after we know we will be able to create the socket
99
fd = new FileDescriptor();
100
try {
101
socketCreate(false);
102
} catch (IOException ioe) {
103
ResourceManager.afterUdpClose();
104
fd = null;
105
throw ioe;
106
}
107
} else {
108
fd = new FileDescriptor();
109
socketCreate(true);
110
}
111
if (socket != null)
112
socket.setCreated();
113
if (serverSocket != null)
114
serverSocket.setCreated();
115
}
116
117
/**
118
* Creates a socket and connects it to the specified port on
119
* the specified host.
120
* @param host the specified host
121
* @param port the specified port
122
*/
123
protected void connect(String host, int port)
124
throws UnknownHostException, IOException
125
{
126
boolean connected = false;
127
try {
128
InetAddress address = InetAddress.getByName(host);
129
this.port = port;
130
this.address = address;
131
132
connectToAddress(address, port, timeout);
133
connected = true;
134
} finally {
135
if (!connected) {
136
try {
137
close();
138
} catch (IOException ioe) {
139
/* Do nothing. If connect threw an exception then
140
it will be passed up the call stack */
141
}
142
}
143
}
144
}
145
146
/**
147
* Creates a socket and connects it to the specified address on
148
* the specified port.
149
* @param address the address
150
* @param port the specified port
151
*/
152
protected void connect(InetAddress address, int port) throws IOException {
153
this.port = port;
154
this.address = address;
155
156
try {
157
connectToAddress(address, port, timeout);
158
return;
159
} catch (IOException e) {
160
// everything failed
161
close();
162
throw e;
163
}
164
}
165
166
/**
167
* Creates a socket and connects it to the specified address on
168
* the specified port.
169
* @param address the address
170
* @param timeout the timeout value in milliseconds, or zero for no timeout.
171
* @throws IOException if connection fails
172
* @throws IllegalArgumentException if address is null or is a
173
* SocketAddress subclass not supported by this socket
174
* @since 1.4
175
*/
176
protected void connect(SocketAddress address, int timeout)
177
throws IOException {
178
boolean connected = false;
179
try {
180
if (address == null || !(address instanceof InetSocketAddress))
181
throw new IllegalArgumentException("unsupported address type");
182
InetSocketAddress addr = (InetSocketAddress) address;
183
if (addr.isUnresolved())
184
throw new UnknownHostException(addr.getHostName());
185
this.port = addr.getPort();
186
this.address = addr.getAddress();
187
188
connectToAddress(this.address, port, timeout);
189
connected = true;
190
} finally {
191
if (!connected) {
192
try {
193
close();
194
} catch (IOException ioe) {
195
/* Do nothing. If connect threw an exception then
196
it will be passed up the call stack */
197
}
198
}
199
}
200
}
201
202
private void connectToAddress(InetAddress address, int port, int timeout) throws IOException {
203
if (address.isAnyLocalAddress()) {
204
doConnect(InetAddress.getLocalHost(), port, timeout);
205
} else {
206
doConnect(address, port, timeout);
207
}
208
}
209
210
public void setOption(int opt, Object val) throws SocketException {
211
if (isClosedOrPending()) {
212
throw new SocketException("Socket Closed");
213
}
214
boolean on = true;
215
switch (opt) {
216
/* check type safety b4 going native. These should never
217
* fail, since only java.Socket* has access to
218
* PlainSocketImpl.setOption().
219
*/
220
case SO_LINGER:
221
if (val == null || (!(val instanceof Integer) && !(val instanceof Boolean)))
222
throw new SocketException("Bad parameter for option");
223
if (val instanceof Boolean) {
224
/* true only if disabling - enabling should be Integer */
225
on = false;
226
}
227
break;
228
case SO_TIMEOUT:
229
if (val == null || (!(val instanceof Integer)))
230
throw new SocketException("Bad parameter for SO_TIMEOUT");
231
int tmp = ((Integer) val).intValue();
232
if (tmp < 0)
233
throw new IllegalArgumentException("timeout < 0");
234
timeout = tmp;
235
break;
236
case IP_TOS:
237
if (val == null || !(val instanceof Integer)) {
238
throw new SocketException("bad argument for IP_TOS");
239
}
240
trafficClass = ((Integer)val).intValue();
241
break;
242
case SO_BINDADDR:
243
throw new SocketException("Cannot re-bind socket");
244
case TCP_NODELAY:
245
if (val == null || !(val instanceof Boolean))
246
throw new SocketException("bad parameter for TCP_NODELAY");
247
on = ((Boolean)val).booleanValue();
248
break;
249
case SO_SNDBUF:
250
case SO_RCVBUF:
251
if (val == null || !(val instanceof Integer) ||
252
!(((Integer)val).intValue() > 0)) {
253
throw new SocketException("bad parameter for SO_SNDBUF " +
254
"or SO_RCVBUF");
255
}
256
break;
257
case SO_KEEPALIVE:
258
if (val == null || !(val instanceof Boolean))
259
throw new SocketException("bad parameter for SO_KEEPALIVE");
260
on = ((Boolean)val).booleanValue();
261
break;
262
case SO_OOBINLINE:
263
if (val == null || !(val instanceof Boolean))
264
throw new SocketException("bad parameter for SO_OOBINLINE");
265
on = ((Boolean)val).booleanValue();
266
break;
267
case SO_REUSEADDR:
268
if (val == null || !(val instanceof Boolean))
269
throw new SocketException("bad parameter for SO_REUSEADDR");
270
on = ((Boolean)val).booleanValue();
271
break;
272
default:
273
throw new SocketException("unrecognized TCP option: " + opt);
274
}
275
socketSetOption(opt, on, val);
276
}
277
public Object getOption(int opt) throws SocketException {
278
if (isClosedOrPending()) {
279
throw new SocketException("Socket Closed");
280
}
281
if (opt == SO_TIMEOUT) {
282
return new Integer(timeout);
283
}
284
int ret = 0;
285
/*
286
* The native socketGetOption() knows about 3 options.
287
* The 32 bit value it returns will be interpreted according
288
* to what we're asking. A return of -1 means it understands
289
* the option but its turned off. It will raise a SocketException
290
* if "opt" isn't one it understands.
291
*/
292
293
switch (opt) {
294
case TCP_NODELAY:
295
ret = socketGetOption(opt, null);
296
return Boolean.valueOf(ret != -1);
297
case SO_OOBINLINE:
298
ret = socketGetOption(opt, null);
299
return Boolean.valueOf(ret != -1);
300
case SO_LINGER:
301
ret = socketGetOption(opt, null);
302
return (ret == -1) ? Boolean.FALSE: (Object)(new Integer(ret));
303
case SO_REUSEADDR:
304
ret = socketGetOption(opt, null);
305
return Boolean.valueOf(ret != -1);
306
case SO_BINDADDR:
307
InetAddressContainer in = new InetAddressContainer();
308
ret = socketGetOption(opt, in);
309
return in.addr;
310
case SO_SNDBUF:
311
case SO_RCVBUF:
312
ret = socketGetOption(opt, null);
313
return new Integer(ret);
314
case IP_TOS:
315
try {
316
ret = socketGetOption(opt, null);
317
if (ret == -1) { // ipv6 tos
318
return trafficClass;
319
} else {
320
return ret;
321
}
322
} catch (SocketException se) {
323
// TODO - should make better effort to read TOS or TCLASS
324
return trafficClass; // ipv6 tos
325
}
326
case SO_KEEPALIVE:
327
ret = socketGetOption(opt, null);
328
return Boolean.valueOf(ret != -1);
329
// should never get here
330
default:
331
return null;
332
}
333
}
334
335
/**
336
* The workhorse of the connection operation. Tries several times to
337
* establish a connection to the given <host, port>. If unsuccessful,
338
* throws an IOException indicating what went wrong.
339
*/
340
341
synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException {
342
synchronized (fdLock) {
343
if (!closePending && (socket == null || !socket.isBound())) {
344
NetHooks.beforeTcpConnect(fd, address, port);
345
}
346
}
347
try {
348
acquireFD();
349
try {
350
socketConnect(address, port, timeout);
351
/* socket may have been closed during poll/select */
352
synchronized (fdLock) {
353
if (closePending) {
354
throw new SocketException ("Socket closed");
355
}
356
}
357
// If we have a ref. to the Socket, then sets the flags
358
// created, bound & connected to true.
359
// This is normally done in Socket.connect() but some
360
// subclasses of Socket may call impl.connect() directly!
361
if (socket != null) {
362
socket.setBound();
363
socket.setConnected();
364
}
365
} finally {
366
releaseFD();
367
}
368
} catch (IOException e) {
369
close();
370
throw e;
371
}
372
}
373
374
/**
375
* Binds the socket to the specified address of the specified local port.
376
* @param address the address
377
* @param lport the port
378
*/
379
protected synchronized void bind(InetAddress address, int lport)
380
throws IOException
381
{
382
synchronized (fdLock) {
383
if (!closePending && (socket == null || !socket.isBound())) {
384
NetHooks.beforeTcpBind(fd, address, lport);
385
}
386
}
387
socketBind(address, lport);
388
if (socket != null)
389
socket.setBound();
390
if (serverSocket != null)
391
serverSocket.setBound();
392
}
393
394
/**
395
* Listens, for a specified amount of time, for connections.
396
* @param count the amount of time to listen for connections
397
*/
398
protected synchronized void listen(int count) throws IOException {
399
socketListen(count);
400
}
401
402
/**
403
* Accepts connections.
404
* @param s the connection
405
*/
406
protected void accept(SocketImpl s) throws IOException {
407
acquireFD();
408
try {
409
socketAccept(s);
410
} finally {
411
releaseFD();
412
}
413
}
414
415
/**
416
* Gets an InputStream for this socket.
417
*/
418
protected synchronized InputStream getInputStream() throws IOException {
419
synchronized (fdLock) {
420
if (isClosedOrPending())
421
throw new IOException("Socket Closed");
422
if (shut_rd)
423
throw new IOException("Socket input is shutdown");
424
if (socketInputStream == null)
425
socketInputStream = new SocketInputStream(this);
426
}
427
return socketInputStream;
428
}
429
430
void setInputStream(SocketInputStream in) {
431
socketInputStream = in;
432
}
433
434
/**
435
* Gets an OutputStream for this socket.
436
*/
437
protected synchronized OutputStream getOutputStream() throws IOException {
438
synchronized (fdLock) {
439
if (isClosedOrPending())
440
throw new IOException("Socket Closed");
441
if (shut_wr)
442
throw new IOException("Socket output is shutdown");
443
if (socketOutputStream == null)
444
socketOutputStream = new SocketOutputStream(this);
445
}
446
return socketOutputStream;
447
}
448
449
void setFileDescriptor(FileDescriptor fd) {
450
this.fd = fd;
451
}
452
453
void setAddress(InetAddress address) {
454
this.address = address;
455
}
456
457
void setPort(int port) {
458
this.port = port;
459
}
460
461
void setLocalPort(int localport) {
462
this.localport = localport;
463
}
464
465
/**
466
* Returns the number of bytes that can be read without blocking.
467
*/
468
protected synchronized int available() throws IOException {
469
if (isClosedOrPending()) {
470
throw new IOException("Stream closed.");
471
}
472
473
/*
474
* If connection has been reset or shut down for input, then return 0
475
* to indicate there are no buffered bytes.
476
*/
477
if (isConnectionReset() || shut_rd) {
478
return 0;
479
}
480
481
/*
482
* If no bytes available and we were previously notified
483
* of a connection reset then we move to the reset state.
484
*
485
* If are notified of a connection reset then check
486
* again if there are bytes buffered on the socket.
487
*/
488
int n = 0;
489
try {
490
n = socketAvailable();
491
if (n == 0 && isConnectionResetPending()) {
492
setConnectionReset();
493
}
494
} catch (ConnectionResetException exc1) {
495
setConnectionResetPending();
496
try {
497
n = socketAvailable();
498
if (n == 0) {
499
setConnectionReset();
500
}
501
} catch (ConnectionResetException exc2) {
502
}
503
}
504
return n;
505
}
506
507
/**
508
* Closes the socket.
509
*/
510
protected void close() throws IOException {
511
synchronized(fdLock) {
512
if (fd != null) {
513
if (!stream) {
514
ResourceManager.afterUdpClose();
515
}
516
if (fdUseCount == 0) {
517
if (closePending) {
518
return;
519
}
520
closePending = true;
521
/*
522
* We close the FileDescriptor in two-steps - first the
523
* "pre-close" which closes the socket but doesn't
524
* release the underlying file descriptor. This operation
525
* may be lengthy due to untransmitted data and a long
526
* linger interval. Once the pre-close is done we do the
527
* actual socket to release the fd.
528
*/
529
try {
530
socketPreClose();
531
} finally {
532
socketClose();
533
}
534
fd = null;
535
return;
536
} else {
537
/*
538
* If a thread has acquired the fd and a close
539
* isn't pending then use a deferred close.
540
* Also decrement fdUseCount to signal the last
541
* thread that releases the fd to close it.
542
*/
543
if (!closePending) {
544
closePending = true;
545
fdUseCount--;
546
socketPreClose();
547
}
548
}
549
}
550
}
551
}
552
553
void reset() throws IOException {
554
if (fd != null) {
555
socketClose();
556
}
557
fd = null;
558
super.reset();
559
}
560
561
562
/**
563
* Shutdown read-half of the socket connection;
564
*/
565
protected void shutdownInput() throws IOException {
566
if (fd != null) {
567
socketShutdown(SHUT_RD);
568
if (socketInputStream != null) {
569
socketInputStream.setEOF(true);
570
}
571
shut_rd = true;
572
}
573
}
574
575
/**
576
* Shutdown write-half of the socket connection;
577
*/
578
protected void shutdownOutput() throws IOException {
579
if (fd != null) {
580
socketShutdown(SHUT_WR);
581
shut_wr = true;
582
}
583
}
584
585
protected boolean supportsUrgentData () {
586
return true;
587
}
588
589
protected void sendUrgentData (int data) throws IOException {
590
if (fd == null) {
591
throw new IOException("Socket Closed");
592
}
593
socketSendUrgentData (data);
594
}
595
596
/**
597
* Cleans up if the user forgets to close it.
598
*/
599
protected void finalize() throws IOException {
600
close();
601
}
602
603
/*
604
* "Acquires" and returns the FileDescriptor for this impl
605
*
606
* A corresponding releaseFD is required to "release" the
607
* FileDescriptor.
608
*/
609
FileDescriptor acquireFD() {
610
synchronized (fdLock) {
611
fdUseCount++;
612
return fd;
613
}
614
}
615
616
/*
617
* "Release" the FileDescriptor for this impl.
618
*
619
* If the use count goes to -1 then the socket is closed.
620
*/
621
void releaseFD() {
622
synchronized (fdLock) {
623
fdUseCount--;
624
if (fdUseCount == -1) {
625
if (fd != null) {
626
try {
627
socketClose();
628
} catch (IOException e) {
629
} finally {
630
fd = null;
631
}
632
}
633
}
634
}
635
}
636
637
public boolean isConnectionReset() {
638
synchronized (resetLock) {
639
return (resetState == CONNECTION_RESET);
640
}
641
}
642
643
public boolean isConnectionResetPending() {
644
synchronized (resetLock) {
645
return (resetState == CONNECTION_RESET_PENDING);
646
}
647
}
648
649
public void setConnectionReset() {
650
synchronized (resetLock) {
651
resetState = CONNECTION_RESET;
652
}
653
}
654
655
public void setConnectionResetPending() {
656
synchronized (resetLock) {
657
if (resetState == CONNECTION_NOT_RESET) {
658
resetState = CONNECTION_RESET_PENDING;
659
}
660
}
661
662
}
663
664
/*
665
* Return true if already closed or close is pending
666
*/
667
public boolean isClosedOrPending() {
668
/*
669
* Lock on fdLock to ensure that we wait if a
670
* close is in progress.
671
*/
672
synchronized (fdLock) {
673
if (closePending || (fd == null)) {
674
return true;
675
} else {
676
return false;
677
}
678
}
679
}
680
681
/*
682
* Return the current value of SO_TIMEOUT
683
*/
684
public int getTimeout() {
685
return timeout;
686
}
687
688
/*
689
* "Pre-close" a socket by dup'ing the file descriptor - this enables
690
* the socket to be closed without releasing the file descriptor.
691
*/
692
private void socketPreClose() throws IOException {
693
socketClose0(true);
694
}
695
696
/*
697
* Close the socket (and release the file descriptor).
698
*/
699
protected void socketClose() throws IOException {
700
socketClose0(false);
701
}
702
703
abstract void socketCreate(boolean isServer) throws IOException;
704
abstract void socketConnect(InetAddress address, int port, int timeout)
705
throws IOException;
706
abstract void socketBind(InetAddress address, int port)
707
throws IOException;
708
abstract void socketListen(int count)
709
throws IOException;
710
abstract void socketAccept(SocketImpl s)
711
throws IOException;
712
abstract int socketAvailable()
713
throws IOException;
714
abstract void socketClose0(boolean useDeferredClose)
715
throws IOException;
716
abstract void socketShutdown(int howto)
717
throws IOException;
718
abstract void socketSetOption(int cmd, boolean on, Object value)
719
throws SocketException;
720
abstract int socketGetOption(int opt, Object iaContainerObj) throws SocketException;
721
abstract void socketSendUrgentData(int data)
722
throws IOException;
723
724
public final static int SHUT_RD = 0;
725
public final static int SHUT_WR = 1;
726
}
727
728