1 /*
2  * Copyright (c) 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 import java.io.InputStream;
24 import java.io.OutputStream;
25 import java.net.InetSocketAddress;
26 import java.net.ServerSocket;
27 import java.net.Socket;
28 import java.net.URI;
29 import java.net.SocketTimeoutException;
30 import java.time.Duration;
31 import javax.net.ssl.SSLServerSocketFactory;
32 import javax.net.ServerSocketFactory;
33 import javax.net.ssl.SSLContext;
34 import javax.net.ssl.SSLParameters;
35 import java.net.http.HttpClient;
36 import java.net.http.HttpRequest;
37 import java.net.http.HttpResponse;
38 import jdk.test.lib.net.SimpleSSLContext;
39 
40 /**
41  * @test
42  * @bug 8207966
43  * @library /test/lib
44  * @build jdk.test.lib.net.SimpleSSLContext
45  * @run main/othervm -Djdk.tls.acknowledgeCloseNotify=true UnknownBodyLengthTest plain false
46  * @run main/othervm -Djdk.tls.acknowledgeCloseNotify=true UnknownBodyLengthTest SSL false
47  * @run main/othervm -Djdk.tls.acknowledgeCloseNotify=true UnknownBodyLengthTest plain true
48  * @run main/othervm -Djdk.tls.acknowledgeCloseNotify=true UnknownBodyLengthTest SSL true
49  */
50 
51 public class UnknownBodyLengthTest {
52     static final byte[] BUF = new byte[32 * 10234 + 2];
53 
54     volatile SSLContext ctx;
55     volatile ServerSocketFactory factory;
56     volatile String clientURL;
57     volatile int port;
58     final ServerSocket ss;
59 
UnknownBodyLengthTest(boolean useSSL)60     UnknownBodyLengthTest(boolean useSSL) throws Exception {
61         ctx = new SimpleSSLContext().get();
62         SSLContext.setDefault(ctx);
63         factory = useSSL ? SSLServerSocketFactory.getDefault()
64                          : ServerSocketFactory.getDefault();
65         ss = factory.createServerSocket();
66         ss.setReuseAddress(true);
67         ss.bind(new InetSocketAddress("127.0.0.1", 0));
68         System.out.println("ServerSocket = " + ss.getClass() + " " + ss);
69         port = ss.getLocalPort();
70         clientURL = (useSSL ? "https" : "http") + "://localhost:"
71             + Integer.toString(port) + "/test";
72     }
73 
fillBuf(byte[] buf)74     static void fillBuf(byte[] buf) {
75         for (int i=0; i<buf.length; i++)
76             buf[i] = (byte)i;
77     }
78 
checkBuf(byte[] buf)79     static void checkBuf(byte[] buf) {
80         if (buf.length != BUF.length)
81             throw new RuntimeException("buffer lengths not the same");
82         for (int i=0; i<buf.length; i++)
83             if (buf[i] != BUF[i])
84                 throw new RuntimeException("error at position " + i);
85     }
86 
server(final boolean withContentLength)87     void server(final boolean withContentLength) {
88         fillBuf(BUF);
89         try {
90             Socket s = ss.accept();
91             s.setTcpNoDelay(true);
92             s.setSoLinger(true, 1);
93             System.out.println("Accepted: "+s.getRemoteSocketAddress());
94             System.out.println("Accepted: "+s);
95             OutputStream os = s.getOutputStream();
96             InputStream is = s.getInputStream();
97             boolean done = false;
98             byte[] buf = new byte[1024];
99             String rsp = "";
100             while (!done) {
101                 int c = is.read(buf);
102                 if (c < 0) break;
103                 String s1 = new String(buf, 0, c, "ISO-8859-1");
104                 rsp += s1;
105                 done = rsp.endsWith("!#!#");
106             }
107             String r = "HTTP/1.0 200 OK\r\nConnection: close\r\nContent-Type:" +
108                        " text/xml; charset=UTF-8\r\n";
109             os.write(r.getBytes());
110             String chdr = "Content-Length: " + Integer.toString(BUF.length) +
111                      "\r\n";
112             System.out.println(chdr);
113             if(withContentLength)
114                 os.write(chdr.getBytes());
115             os.write("\r\n".getBytes());
116             os.write(BUF);
117             if (is.available() > 0)
118                 is.read(buf);
119             os.flush();
120             os.close();
121             s.shutdownOutput();
122             s.close();
123         } catch(final Throwable t) {
124           t.printStackTrace();
125         } finally {
126             try {ss.close(); } catch (Exception e) {}
127         }
128     }
129 
client(boolean useSSL)130     void client(boolean useSSL) throws Exception {
131         SSLContext ctx = SSLContext.getDefault();
132         HttpClient.Builder clientB = HttpClient.newBuilder()
133             .version(HttpClient.Version.HTTP_2);
134         if (useSSL) {
135             clientB = clientB.sslContext(ctx)
136                 .sslParameters(ctx.getSupportedSSLParameters());
137         }
138         final HttpClient client = clientB.build();
139 
140         System.out.println("URL: " + clientURL);
141         final HttpResponse<byte[]> response = client
142             .send(HttpRequest
143                 .newBuilder(new URI(clientURL))
144                 .timeout(Duration.ofMillis(120_000))
145                 .POST(HttpRequest.BodyPublishers.ofString("body!#!#"))
146                 .build(), HttpResponse.BodyHandlers.ofByteArray());
147 
148         System.out.println("Received reply: " + response.statusCode());
149         byte[] bb = response.body();
150         checkBuf(bb);
151     }
152 
main(final String[] args)153     public static void main(final String[] args) throws Exception {
154         boolean ssl = args[0].equals("SSL");
155         boolean fixedlen = args[1].equals("true");
156         UnknownBodyLengthTest test = new UnknownBodyLengthTest(ssl);
157         test.run(ssl, fixedlen);
158     }
159 
run(boolean ssl, boolean fixedlen)160     public void run(boolean ssl, boolean fixedlen) throws Exception {
161         new Thread(()->server(fixedlen)).start();
162         client(ssl);
163     }
164 }
165