Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/java/nio/channels/TestServers.java
41149 views
1
/*
2
* Copyright (c) 2012, 2018, 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.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
/* Test utility classes
25
*
26
*/
27
28
import java.io.*;
29
import java.net.*;
30
import java.util.ArrayList;
31
import java.util.Date;
32
import java.util.List;
33
34
import jdk.test.lib.Utils;
35
36
37
public class TestServers {
38
39
private TestServers() { }
40
41
/**
42
* An abstract server identifies a server which listens on a port on on a
43
* given machine.
44
*/
45
static abstract class AbstractServer {
46
47
private AbstractServer() {
48
}
49
50
public abstract int getPort();
51
52
public abstract InetAddress getAddress();
53
}
54
55
/**
56
* A downgraded type of AbstractServer which will refuse connections. Note:
57
* use it once and throw it away - this implementation opens an anonymous
58
* socket and closes it, returning the address of the closed socket. If
59
* other servers are started afterwards, the address/port might get reused
60
* and become connectable again - so it's not a good idea to assume that
61
* connections using this address/port will always be refused. Connections
62
* will be refused as long as the address/port of the refusing server has
63
* not been reused.
64
*/
65
static class RefusingServer extends AbstractServer {
66
67
final InetAddress address;
68
final int port;
69
70
private RefusingServer(InetAddress address, int port) {
71
this.address = address;
72
this.port = port;
73
}
74
75
@Override
76
public int getPort() {
77
return port;
78
}
79
80
@Override
81
public InetAddress getAddress() {
82
return address;
83
}
84
85
public static RefusingServer newRefusingServer() throws IOException {
86
return new RefusingServer(InetAddress.getLocalHost(),
87
Utils.refusingEndpoint().getPort());
88
}
89
}
90
91
/**
92
* An abstract class for implementing small TCP servers for the nio tests
93
* purposes. Disclaimer: This is a naive implementation that uses the old
94
* networking APIs (not those from {@code java.nio.*}) and shamelessly
95
* extends/creates Threads instead of using an executor service.
96
*/
97
static abstract class AbstractTcpServer extends AbstractServer
98
implements Runnable, Closeable {
99
100
protected final long linger; // #of ms to wait before responding
101
private Thread acceptThread; // thread waiting for accept
102
// list of opened connections that should be closed on close.
103
private List<TcpConnectionThread> connections = new ArrayList<>();
104
private ServerSocket serverSocket; // the server socket
105
private boolean started = false; // whether the server is started
106
Throwable error = null;
107
108
/**
109
* Creates a new abstract TCP server.
110
*
111
* @param linger the amount of time the server should wait before
112
* responding to requests.
113
*/
114
protected AbstractTcpServer(long linger) {
115
this.linger = linger;
116
}
117
118
/**
119
* The local port to which the server is bound.
120
*
121
* @return The local port to which the server is bound.
122
* @exception IllegalStateException is thrown if the server is not
123
* started.
124
*/
125
@Override
126
public final synchronized int getPort() {
127
if (!started) {
128
throw new IllegalStateException("Not started");
129
}
130
return serverSocket.getLocalPort();
131
}
132
133
/**
134
* The local address to which the server is bound.
135
*
136
* @return The local address to which the server is bound.
137
* @exception IllegalStateException is thrown if the server is not
138
* started.
139
*/
140
@Override
141
public final synchronized InetAddress getAddress() {
142
if (!started) {
143
throw new IllegalStateException("Not started");
144
}
145
return serverSocket.getInetAddress();
146
}
147
148
/**
149
* Tells whether the server is started.
150
*
151
* @return true if the server is started.
152
*/
153
public final synchronized boolean isStarted() {
154
return started;
155
}
156
157
/**
158
* Creates a new server socket.
159
*
160
* @param port local port to bind to.
161
* @param backlog requested maximum length of the queue of incoming
162
* connections.
163
* @param address local address to bind to.
164
* @return a new bound server socket ready to accept connections.
165
* @throws IOException if the socket cannot be created or bound.
166
*/
167
protected ServerSocket newServerSocket(int port, int backlog,
168
InetAddress address)
169
throws IOException {
170
return new ServerSocket(port, backlog, address);
171
}
172
173
/**
174
* Starts listening for connections.
175
*
176
* @throws IOException if the server socket cannot be created or bound.
177
*/
178
public final synchronized void start() throws IOException {
179
if (started) {
180
return;
181
}
182
final ServerSocket socket =
183
newServerSocket(0, 100, InetAddress.getLocalHost());
184
serverSocket = socket;
185
acceptThread = new Thread(this);
186
acceptThread.setDaemon(true);
187
acceptThread.start();
188
started = true;
189
}
190
191
/**
192
* Calls {@code Thread.sleep(linger);}
193
*/
194
protected final void lingerIfRequired() {
195
if (linger > 0) {
196
try {
197
Thread.sleep(linger);
198
} catch (InterruptedException x) {
199
Thread.interrupted();
200
final ServerSocket socket = serverSocket();
201
if (socket != null && !socket.isClosed()) {
202
System.err.println("Thread interrupted...");
203
}
204
}
205
}
206
}
207
208
final synchronized ServerSocket serverSocket() {
209
return this.serverSocket;
210
}
211
212
/**
213
* The main accept loop.
214
*/
215
@Override
216
public final void run() {
217
final ServerSocket sSocket = serverSocket();
218
try {
219
Socket s;
220
while (isStarted() && !Thread.interrupted()
221
&& (s = sSocket.accept()) != null) {
222
lingerIfRequired();
223
listen(s);
224
}
225
} catch (Exception x) {
226
error = x;
227
} finally {
228
synchronized (this) {
229
if (!sSocket.isClosed()) {
230
try {
231
sSocket.close();
232
} catch (IOException x) {
233
System.err.println("Failed to close server socket");
234
}
235
}
236
if (started && this.serverSocket == sSocket) {
237
started = false;
238
this.serverSocket = null;
239
this.acceptThread = null;
240
}
241
}
242
}
243
}
244
245
/**
246
* Represents a connection accepted by the server.
247
*/
248
protected abstract class TcpConnectionThread extends Thread {
249
250
protected final Socket socket;
251
252
protected TcpConnectionThread(Socket socket) {
253
this.socket = socket;
254
this.setDaemon(true);
255
}
256
257
public void close() throws IOException {
258
socket.close();
259
interrupt();
260
}
261
}
262
263
/**
264
* Creates a new TcpConnnectionThread to handle the connection through
265
* an accepted socket.
266
*
267
* @param s the socket returned by {@code serverSocket.accept()}.
268
* @return a new TcpConnnectionThread to handle the connection through
269
* an accepted socket.
270
*/
271
protected abstract TcpConnectionThread createConnection(Socket s);
272
273
/**
274
* Creates and starts a new TcpConnectionThread to handle the accepted
275
* socket.
276
*
277
* @param s the socket returned by {@code serverSocket.accept()}.
278
*/
279
private synchronized void listen(Socket s) {
280
TcpConnectionThread c = createConnection(s);
281
c.start();
282
addConnection(c);
283
}
284
285
/**
286
* Add the connection to the list of accepted connections.
287
*
288
* @param connection an accepted connection.
289
*/
290
protected synchronized void addConnection(
291
TcpConnectionThread connection) {
292
connections.add(connection);
293
}
294
295
/**
296
* Remove the connection from the list of accepted connections.
297
*
298
* @param connection an accepted connection.
299
*/
300
protected synchronized void removeConnection(
301
TcpConnectionThread connection) {
302
connections.remove(connection);
303
}
304
305
/**
306
* Close the server socket and all the connections present in the list
307
* of accepted connections.
308
*
309
* @throws IOException
310
*/
311
@Override
312
public synchronized void close() throws IOException {
313
if (serverSocket != null && !serverSocket.isClosed()) {
314
serverSocket.close();
315
}
316
if (acceptThread != null) {
317
acceptThread.interrupt();
318
}
319
int failed = 0;
320
for (TcpConnectionThread c : connections) {
321
try {
322
c.close();
323
} catch (IOException x) {
324
// no matter - we're closing.
325
failed++;
326
}
327
}
328
connections.clear();
329
if (failed > 0) {
330
throw new IOException("Failed to close some connections");
331
}
332
}
333
}
334
335
/**
336
* A small TCP Server that emulates the echo service for tests purposes. See
337
* http://en.wikipedia.org/wiki/Echo_Protocol This server uses an anonymous
338
* port - NOT the standard port 7. We don't guarantee that its behavior
339
* exactly matches the RFC - the only purpose of this server is to have
340
* something that responds to nio tests...
341
*/
342
static class EchoServer extends AbstractTcpServer {
343
344
public EchoServer() {
345
this(0L);
346
}
347
348
public EchoServer(long linger) {
349
super(linger);
350
}
351
352
@Override
353
protected TcpConnectionThread createConnection(Socket s) {
354
return new EchoConnection(s);
355
}
356
357
private final class EchoConnection extends TcpConnectionThread {
358
359
public EchoConnection(Socket socket) {
360
super(socket);
361
}
362
363
@Override
364
public void run() {
365
try {
366
final InputStream is = socket.getInputStream();
367
final OutputStream out = socket.getOutputStream();
368
byte[] b = new byte[255];
369
int n;
370
while ((n = is.read(b)) > 0) {
371
lingerIfRequired();
372
out.write(b, 0, n);
373
}
374
} catch (IOException io) {
375
// fall through to finally
376
} finally {
377
if (!socket.isClosed()) {
378
try {
379
socket.close();
380
} catch (IOException x) {
381
System.err.println(
382
"Failed to close echo connection socket");
383
}
384
}
385
removeConnection(this);
386
}
387
}
388
}
389
390
public static EchoServer startNewServer() throws IOException {
391
return startNewServer(0);
392
}
393
394
public static EchoServer startNewServer(long linger) throws IOException {
395
final EchoServer echoServer = new EchoServer(linger);
396
echoServer.start();
397
return echoServer;
398
}
399
}
400
401
/**
402
* A small TCP Server that accept connections but does not response to any input.
403
*/
404
static final class NoResponseServer extends EchoServer {
405
public NoResponseServer() {
406
super(Long.MAX_VALUE);
407
}
408
409
public static NoResponseServer startNewServer() throws IOException {
410
final NoResponseServer noResponseServer = new NoResponseServer();
411
noResponseServer.start();
412
return noResponseServer;
413
}
414
}
415
416
/**
417
* A small TCP server that emulates the Day & Time service for tests
418
* purposes. See http://en.wikipedia.org/wiki/Daytime_Protocol This server
419
* uses an anonymous port - NOT the standard port 13. We don't guarantee
420
* that its behavior exactly matches the RFC - the only purpose of this
421
* server is to have something that responds to nio tests...
422
*/
423
static final class DayTimeServer extends AbstractTcpServer {
424
425
public DayTimeServer() {
426
this(0L);
427
}
428
429
public DayTimeServer(long linger) {
430
super(linger);
431
}
432
433
@Override
434
protected TcpConnectionThread createConnection(Socket s) {
435
return new DayTimeServerConnection(s);
436
}
437
438
@Override
439
protected void addConnection(TcpConnectionThread connection) {
440
// do nothing - the connection just write the date and terminates.
441
}
442
443
@Override
444
protected void removeConnection(TcpConnectionThread connection) {
445
// do nothing - we're not adding connections to the list...
446
}
447
448
private final class DayTimeServerConnection extends TcpConnectionThread {
449
450
public DayTimeServerConnection(Socket socket) {
451
super(socket);
452
}
453
454
@Override
455
public void run() {
456
try {
457
final OutputStream out = socket.getOutputStream();
458
lingerIfRequired();
459
out.write(new Date(System.currentTimeMillis())
460
.toString().getBytes("US-ASCII"));
461
out.flush();
462
} catch (IOException io) {
463
// fall through to finally
464
} finally {
465
if (!socket.isClosed()) {
466
try {
467
socket.close();
468
} catch (IOException x) {
469
System.err.println(
470
"Failed to close echo connection socket");
471
}
472
}
473
}
474
}
475
}
476
477
public static DayTimeServer startNewServer()
478
throws IOException {
479
return startNewServer(0);
480
}
481
482
public static DayTimeServer startNewServer(long linger)
483
throws IOException {
484
final DayTimeServer daytimeServer = new DayTimeServer(linger);
485
daytimeServer.start();
486
return daytimeServer;
487
}
488
}
489
490
/**
491
* An abstract class for implementing small UDP Servers for the nio tests
492
* purposes. Disclaimer: This is a naive implementation that uses the old
493
* networking APIs (not those from {@code java.nio.*}) and shamelessly
494
* extends/creates Threads instead of using an executor service.
495
*/
496
static abstract class AbstractUdpServer extends AbstractServer
497
implements Runnable, Closeable {
498
499
protected final long linger; // #of ms to wait before responding
500
private Thread acceptThread; // thread waiting for packets
501
private DatagramSocket serverSocket; // the server socket
502
private boolean started = false; // whether the server is started
503
Throwable error = null;
504
505
/**
506
* Creates a new abstract UDP server.
507
*
508
* @param linger the amount of time the server should wait before
509
* responding to requests.
510
*/
511
protected AbstractUdpServer(long linger) {
512
this.linger = linger;
513
}
514
515
/**
516
* The local port to which the server is bound.
517
*
518
* @return The local port to which the server is bound.
519
* @exception IllegalStateException is thrown if the server is not
520
* started.
521
*/
522
@Override
523
public final synchronized int getPort() {
524
if (!started) {
525
throw new IllegalStateException("Not started");
526
}
527
return serverSocket.getLocalPort();
528
}
529
530
/**
531
* The local address to which the server is bound.
532
*
533
* @return The local address to which the server is bound.
534
* @exception IllegalStateException is thrown if the server is not
535
* started.
536
*/
537
@Override
538
public final synchronized InetAddress getAddress() {
539
if (!started) {
540
throw new IllegalStateException("Not started");
541
}
542
return serverSocket.getLocalAddress();
543
}
544
545
/**
546
* Tells whether the server is started.
547
*
548
* @return true if the server is started.
549
*/
550
public final synchronized boolean isStarted() {
551
return started;
552
}
553
554
/**
555
* Creates a new datagram socket.
556
*
557
* @param port local port to bind to.
558
* @param address local address to bind to.
559
* @return a new bound server socket ready to listen for packets.
560
* @throws IOException if the socket cannot be created or bound.
561
*/
562
protected DatagramSocket newDatagramSocket(int port,
563
InetAddress address)
564
throws IOException {
565
return new DatagramSocket(port, address);
566
}
567
568
/**
569
* Starts listening for connections.
570
*
571
* @throws IOException if the server socket cannot be created or bound.
572
*/
573
public final synchronized void start() throws IOException {
574
if (started) {
575
return;
576
}
577
final DatagramSocket socket =
578
newDatagramSocket(0, InetAddress.getLocalHost());
579
serverSocket = socket;
580
acceptThread = new Thread(this);
581
acceptThread.setDaemon(true);
582
acceptThread.start();
583
started = true;
584
}
585
586
/**
587
* Calls {@code Thread.sleep(linger);}
588
*/
589
protected final void lingerIfRequired() {
590
if (linger > 0) {
591
try {
592
Thread.sleep(linger);
593
} catch (InterruptedException x) {
594
Thread.interrupted();
595
final DatagramSocket socket = serverSocket();
596
if (socket != null && !socket.isClosed()) {
597
System.err.println("Thread interrupted...");
598
}
599
}
600
}
601
}
602
603
final synchronized DatagramSocket serverSocket() {
604
return this.serverSocket;
605
}
606
607
final synchronized boolean send(DatagramSocket socket,
608
DatagramPacket response) throws IOException {
609
if (!socket.isClosed()) {
610
socket.send(response);
611
return true;
612
} else {
613
return false;
614
}
615
}
616
617
/**
618
* The main receive loop.
619
*/
620
@Override
621
public final void run() {
622
final DatagramSocket sSocket = serverSocket();
623
try {
624
final int size = Math.max(1024, sSocket.getReceiveBufferSize());
625
if (size > sSocket.getReceiveBufferSize()) {
626
sSocket.setReceiveBufferSize(size);
627
}
628
while (isStarted() && !Thread.interrupted() && !sSocket.isClosed()) {
629
final byte[] buf = new byte[size];
630
final DatagramPacket packet =
631
new DatagramPacket(buf, buf.length);
632
lingerIfRequired();
633
sSocket.receive(packet);
634
//System.out.println("Received packet from: "
635
// + packet.getAddress()+":"+packet.getPort());
636
handle(sSocket, packet);
637
}
638
} catch (Exception x) {
639
error = x;
640
} finally {
641
synchronized (this) {
642
if (!sSocket.isClosed()) {
643
sSocket.close();
644
}
645
if (started && this.serverSocket == sSocket) {
646
started = false;
647
this.serverSocket = null;
648
this.acceptThread = null;
649
}
650
}
651
}
652
}
653
654
/**
655
* Represents an UDP request received by the server.
656
*/
657
protected abstract class UdpRequestThread extends Thread {
658
659
protected final DatagramPacket request;
660
protected final DatagramSocket socket;
661
662
protected UdpRequestThread(DatagramSocket socket, DatagramPacket request) {
663
this.socket = socket;
664
this.request = request;
665
this.setDaemon(true);
666
}
667
}
668
669
/**
670
* Creates a new UdpRequestThread to handle a DatagramPacket received
671
* through a DatagramSocket.
672
*
673
* @param socket the socket through which the request was received.
674
* @param request the datagram packet received through the socket.
675
* @return a new UdpRequestThread to handle the request received through
676
* a DatagramSocket.
677
*/
678
protected abstract UdpRequestThread createConnection(DatagramSocket socket,
679
DatagramPacket request);
680
681
/**
682
* Creates and starts a new UdpRequestThread to handle the received
683
* datagram packet.
684
*
685
* @param socket the socket through which the request was received.
686
* @param request the datagram packet received through the socket.
687
*/
688
private synchronized void handle(DatagramSocket socket,
689
DatagramPacket request) {
690
UdpRequestThread c = createConnection(socket, request);
691
// c can be null if the request requires no response.
692
if (c != null) {
693
c.start();
694
}
695
}
696
697
/**
698
* Close the server socket.
699
*
700
* @throws IOException
701
*/
702
@Override
703
public synchronized void close() throws IOException {
704
if (serverSocket != null && !serverSocket.isClosed()) {
705
serverSocket.close();
706
}
707
if (acceptThread != null) {
708
acceptThread.interrupt();
709
}
710
}
711
}
712
713
/**
714
* A small UDP Server that emulates the discard service for tests purposes.
715
* See http://en.wikipedia.org/wiki/Discard_Protocol This server uses an
716
* anonymous port - NOT the standard port 9. We don't guarantee that its
717
* behavior exactly matches the RFC - the only purpose of this server is to
718
* have something that responds to nio tests...
719
*/
720
static final class UdpDiscardServer extends AbstractUdpServer {
721
722
public UdpDiscardServer() {
723
this(0L);
724
}
725
726
public UdpDiscardServer(long linger) {
727
super(linger);
728
}
729
730
@Override
731
protected UdpRequestThread createConnection(DatagramSocket socket,
732
DatagramPacket request) {
733
// no response required
734
return null;
735
}
736
737
public static UdpDiscardServer startNewServer() throws IOException {
738
return startNewServer(0);
739
}
740
741
public static UdpDiscardServer startNewServer(long linger) throws IOException {
742
final UdpDiscardServer discardServer = new UdpDiscardServer(linger);
743
discardServer.start();
744
return discardServer;
745
}
746
}
747
748
/**
749
* A small UDP Server that emulates the echo service for tests purposes. See
750
* http://en.wikipedia.org/wiki/Echo_Protocol This server uses an anonymous
751
* port - NOT the standard port 7. We don't guarantee that its behavior
752
* exactly matches the RFC - the only purpose of this server is to have
753
* something that responds to nio tests...
754
*/
755
static final class UdpEchoServer extends AbstractUdpServer {
756
757
public UdpEchoServer() {
758
this(0L);
759
}
760
761
public UdpEchoServer(long linger) {
762
super(linger);
763
}
764
765
@Override
766
protected UdpEchoRequest createConnection(DatagramSocket socket,
767
DatagramPacket request) {
768
return new UdpEchoRequest(socket, request);
769
}
770
771
private final class UdpEchoRequest extends UdpRequestThread {
772
773
public UdpEchoRequest(DatagramSocket socket, DatagramPacket request) {
774
super(socket, request);
775
}
776
777
@Override
778
public void run() {
779
try {
780
lingerIfRequired();
781
final DatagramPacket response =
782
new DatagramPacket(request.getData(),
783
request.getOffset(), request.getLength(),
784
request.getAddress(), request.getPort());
785
send(socket, response);
786
} catch (IOException io) {
787
System.err.println("Failed to send response: " + io);
788
io.printStackTrace(System.err);
789
}
790
}
791
}
792
793
public static UdpEchoServer startNewServer() throws IOException {
794
return startNewServer(0);
795
}
796
797
public static UdpEchoServer startNewServer(long linger) throws IOException {
798
final UdpEchoServer echoServer = new UdpEchoServer(linger);
799
echoServer.start();
800
return echoServer;
801
}
802
}
803
804
/**
805
* A small UDP server that emulates the Day & Time service for tests
806
* purposes. See http://en.wikipedia.org/wiki/Daytime_Protocol This server
807
* uses an anonymous port - NOT the standard port 13. We don't guarantee
808
* that its behavior exactly matches the RFC - the only purpose of this
809
* server is to have something that responds to nio tests...
810
*/
811
static final class UdpDayTimeServer extends AbstractUdpServer {
812
813
public UdpDayTimeServer() {
814
this(0L);
815
}
816
817
public UdpDayTimeServer(long linger) {
818
super(linger);
819
}
820
821
@Override
822
protected UdpDayTimeRequestThread createConnection(DatagramSocket socket,
823
DatagramPacket request) {
824
return new UdpDayTimeRequestThread(socket, request);
825
}
826
827
private final class UdpDayTimeRequestThread extends UdpRequestThread {
828
829
public UdpDayTimeRequestThread(DatagramSocket socket,
830
DatagramPacket request) {
831
super(socket, request);
832
}
833
834
@Override
835
public void run() {
836
try {
837
lingerIfRequired();
838
final byte[] data = new Date(System.currentTimeMillis())
839
.toString().getBytes("US-ASCII");
840
final DatagramPacket response =
841
new DatagramPacket(data, 0, data.length,
842
request.getAddress(), request.getPort());
843
send(socket, response);
844
} catch (IOException io) {
845
System.err.println("Failed to send response: " + io);
846
io.printStackTrace(System.err);
847
}
848
}
849
}
850
851
public static UdpDayTimeServer startNewServer() throws IOException {
852
return startNewServer(0);
853
}
854
855
public static UdpDayTimeServer startNewServer(long linger)
856
throws IOException {
857
final UdpDayTimeServer echoServer = new UdpDayTimeServer(linger);
858
echoServer.start();
859
return echoServer;
860
}
861
}
862
}
863
864