test/jdk/java/net/httpclient/http2/server/Http2TestServerConnection.java
author chegar
Mon, 23 Jul 2018 11:47:03 +0100
branchhttp-client-branch
changeset 56839 8ca7b2673b12
parent 56795 03ece2518428
child 56842 43c3b82728eb
permissions -rw-r--r--
http-client-branch: fix for 8207959 The initial value of SETTINGS_MAX_CONCURRENT_STREAMS should have no limit
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
     1
/*
48523
b95b08f3e1a8 8194883: Unhandleable Push Promises should be cancelled
chegar
parents: 48083
diff changeset
     2
 * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
     4
 *
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
     7
 * published by the Free Software Foundation.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
     8
 *
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    13
 * accompanied this code).
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    14
 *
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    18
 *
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    21
 * questions.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    22
 */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    23
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    24
import java.io.BufferedInputStream;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    25
import java.io.BufferedOutputStream;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    26
import java.io.Closeable;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    27
import java.io.IOException;
45713
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
    28
import java.io.UncheckedIOException;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    29
import java.io.InputStream;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    30
import java.io.OutputStream;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    31
import java.net.Socket;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    32
import java.net.URI;
45713
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
    33
import java.net.InetAddress;
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
    34
import javax.net.ssl.*;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    35
import java.net.URISyntaxException;
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
    36
import java.net.http.HttpHeaders;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    37
import java.nio.ByteBuffer;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    38
import java.util.*;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    39
import java.util.concurrent.CompletableFuture;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    40
import java.util.concurrent.ExecutorService;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    41
import java.util.concurrent.ConcurrentLinkedQueue;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    42
import java.util.function.Consumer;
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
    43
import jdk.internal.net.http.common.HttpHeadersBuilder;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
    44
import jdk.internal.net.http.frame.*;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
    45
import jdk.internal.net.http.hpack.Decoder;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
    46
import jdk.internal.net.http.hpack.DecodingCallback;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
    47
import jdk.internal.net.http.hpack.Encoder;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    48
import sun.net.www.http.ChunkedInputStream;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    49
import sun.net.www.http.HttpClient;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
    50
import static jdk.internal.net.http.frame.SettingsFrame.HEADER_TABLE_SIZE;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    51
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    52
/**
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    53
 * Represents one HTTP2 connection, either plaintext upgraded from HTTP/1.1
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    54
 * or HTTPS opened using "h2" ALPN.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    55
 */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    56
public class Http2TestServerConnection {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    57
    final Http2TestServer server;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    58
    @SuppressWarnings({"rawtypes","unchecked"})
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    59
    final Map<Integer, Queue> streams; // input q per stream
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    60
    final Map<Integer, BodyOutputStream> outStreams; // output q per stream
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    61
    final HashSet<Integer> pushStreams;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    62
    final Queue<Http2Frame> outputQ;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    63
    volatile int nextstream;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    64
    final Socket socket;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    65
    final Http2TestExchangeSupplier exchangeSupplier;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    66
    final InputStream is;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    67
    final OutputStream os;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    68
    volatile Encoder hpackOut;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    69
    volatile Decoder hpackIn;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    70
    volatile SettingsFrame clientSettings;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    71
    final SettingsFrame serverSettings;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    72
    final ExecutorService exec;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    73
    final boolean secure;
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
    74
    final Properties properties;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    75
    volatile boolean stopping;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    76
    volatile int nextPushStreamId = 2;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    77
    ConcurrentLinkedQueue<PingRequest> pings = new ConcurrentLinkedQueue<>();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    78
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    79
    final static ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    80
    final static byte[] EMPTY_BARRAY = new byte[0];
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    81
    final Random random;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    82
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    83
    final static byte[] clientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n".getBytes();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    84
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    85
    static class Sentinel extends Http2Frame {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    86
        Sentinel() { super(-1,-1);}
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    87
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    88
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    89
    static final Sentinel sentinel = new Sentinel();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    90
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    91
    class PingRequest {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    92
        final byte[] pingData;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    93
        final long pingStamp;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    94
        final CompletableFuture<Long> response;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    95
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    96
        PingRequest() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    97
            pingData = new byte[8];
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    98
            random.nextBytes(pingData);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    99
            pingStamp = System.currentTimeMillis();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   100
            response = new CompletableFuture<>();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   101
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   102
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   103
        PingFrame frame() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   104
            return new PingFrame(0, pingData);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   105
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   106
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   107
        CompletableFuture<Long> response() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   108
            return response;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   109
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   110
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   111
        void success() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   112
            response.complete(System.currentTimeMillis() - pingStamp);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   113
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   114
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   115
        void fail(Throwable t) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   116
            response.completeExceptionally(t);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   117
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   118
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   119
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   120
    Http2TestServerConnection(Http2TestServer server,
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   121
                              Socket socket,
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   122
                              Http2TestExchangeSupplier exchangeSupplier,
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   123
                              Properties properties)
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   124
        throws IOException
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   125
    {
45713
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   126
        if (socket instanceof SSLSocket) {
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   127
            handshake(server.serverName(), (SSLSocket)socket);
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   128
        }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   129
        System.err.println("TestServer: New connection from " + socket);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   130
        this.server = server;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   131
        this.exchangeSupplier = exchangeSupplier;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   132
        this.streams = Collections.synchronizedMap(new HashMap<>());
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   133
        this.outStreams = Collections.synchronizedMap(new HashMap<>());
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   134
        this.outputQ = new Queue<>(sentinel);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   135
        this.random = new Random();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   136
        this.socket = socket;
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   137
        this.properties = properties;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   138
        this.socket.setTcpNoDelay(true);
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   139
        this.serverSettings = getServerSettingProperties();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   140
        this.exec = server.exec;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   141
        this.secure = server.secure;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   142
        this.pushStreams = new HashSet<>();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   143
        is = new BufferedInputStream(socket.getInputStream());
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   144
        os = new BufferedOutputStream(socket.getOutputStream());
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   145
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   146
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   147
    static final String propPrefix = "http2server.settings.";
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   148
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   149
    static final String[][] propIDs = {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   150
        {"header_table_size", Integer.toString(SettingsFrame.HEADER_TABLE_SIZE)},
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   151
        {"enable_push", Integer.toString(SettingsFrame.ENABLE_PUSH)},
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   152
        {"max_concurrent_streams", Integer.toString(SettingsFrame.MAX_CONCURRENT_STREAMS)},
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   153
        {"initial_window_size", Integer.toString(SettingsFrame.INITIAL_WINDOW_SIZE)},
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   154
        {"max_frame_size", Integer.toString(SettingsFrame.MAX_FRAME_SIZE)},
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   155
        {"max_header_list_size", Integer.toString(SettingsFrame.MAX_HEADER_LIST_SIZE)}
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   156
    };
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   157
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   158
    private SettingsFrame getServerSettingProperties() {
56839
8ca7b2673b12 http-client-branch: fix for 8207959 The initial value of SETTINGS_MAX_CONCURRENT_STREAMS should have no limit
chegar
parents: 56795
diff changeset
   159
        SettingsFrame s = SettingsFrame.defaultRFCSettings();
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   160
        if (properties == null)
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   161
            return s;
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   162
        for (int i=0; i<propIDs.length; i++) {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   163
            String key = propIDs[i][0];
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   164
            String numS = propIDs[i][1];
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   165
            String prop = properties.getProperty(propPrefix + key);
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   166
            if (prop != null) {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   167
                try {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   168
                    System.err.println("TestServer: setting " + key + " property to: " +
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   169
                        prop);
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   170
                    int num = Integer.parseInt(numS);
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   171
                    System.err.println("TestServer: num = " + num);
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   172
                    s.setParameter(num, Integer.parseInt(prop));
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   173
                } catch (NumberFormatException e) {/* ignore errors */}
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   174
            }
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   175
        }
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   176
        return s;
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   177
    }
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   178
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   179
    /**
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   180
     * Sends a PING frame on this connection, and completes the returned
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   181
     * CF when the PING ack is received. The CF is given
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   182
     * an integer, whose value is the number of milliseconds
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   183
     * between PING and ACK.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   184
     */
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   185
    CompletableFuture<Long> sendPing() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   186
        PingRequest ping = null;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   187
        try {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   188
            ping = new PingRequest();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   189
            pings.add(ping);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   190
            outputQ.put(ping.frame());
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   191
        } catch (Throwable t) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   192
            ping.fail(t);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   193
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   194
        return ping.response();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   195
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   196
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   197
    void goAway(int error) throws IOException {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   198
        int laststream = nextstream >= 3 ? nextstream - 2 : 1;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   199
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   200
        GoAwayFrame go = new GoAwayFrame(laststream, error);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   201
        outputQ.put(go);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   202
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   203
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   204
    /**
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   205
     * Returns the first PingRequest from Queue
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   206
     */
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   207
    private PingRequest getNextRequest() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   208
        return pings.poll();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   209
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   210
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   211
    /**
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   212
     * Handles incoming Ping, which could be an ack
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   213
     * or a client originated Ping
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   214
     */
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   215
    void handlePing(PingFrame ping) throws IOException {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   216
        if (ping.streamid() != 0) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   217
            System.err.println("Invalid ping received");
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   218
            close(ErrorFrame.PROTOCOL_ERROR);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   219
            return;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   220
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   221
        if (ping.getFlag(PingFrame.ACK)) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   222
            // did we send a Ping?
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   223
            PingRequest request = getNextRequest();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   224
            if (request == null) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   225
                System.err.println("Invalid ping ACK received");
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   226
                close(ErrorFrame.PROTOCOL_ERROR);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   227
                return;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   228
            } else if (!Arrays.equals(request.pingData, ping.getData())) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   229
                request.fail(new RuntimeException("Wrong ping data in ACK"));
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   230
            } else {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   231
                request.success();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   232
            }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   233
        } else {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   234
            // client originated PING. Just send it back with ACK set
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   235
            ping.setFlag(PingFrame.ACK);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   236
            outputQ.put(ping);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   237
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   238
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   239
45713
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   240
    private static boolean compareIPAddrs(InetAddress addr1, String host) {
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   241
        try {
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   242
            InetAddress addr2 = InetAddress.getByName(host);
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   243
            return addr1.equals(addr2);
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   244
        } catch (IOException e) {
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   245
            throw new UncheckedIOException(e);
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   246
        }
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   247
    }
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   248
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   249
    private static void handshake(String name, SSLSocket sock) throws IOException {
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   250
        if (name == null) {
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   251
            // no name set. No need to check
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   252
            return;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   253
        } else if (name.equals("localhost")) {
45713
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   254
            name = "localhost";
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   255
        }
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   256
        final String fname = name;
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   257
        final InetAddress addr1 = InetAddress.getByName(name);
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   258
        SSLParameters params = sock.getSSLParameters();
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   259
        SNIMatcher matcher = new SNIMatcher(StandardConstants.SNI_HOST_NAME) {
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   260
            public boolean matches (SNIServerName n) {
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   261
                String host = ((SNIHostName)n).getAsciiName();
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   262
                if (host.equals("localhost"))
45713
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   263
                    host = "localhost";
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   264
                boolean cmp = host.equalsIgnoreCase(fname);
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   265
                if (cmp)
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   266
                    return true;
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   267
                return compareIPAddrs(addr1, host);
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   268
            }
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   269
        };
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   270
        List<SNIMatcher> list = List.of(matcher);
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   271
        params.setSNIMatchers(list);
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   272
        sock.setSSLParameters(params);
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   273
        sock.getSession(); // blocks until handshake done
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   274
    }
ee3f2cbfe23a 8182589: TLS SNI in new Java 9 client is not available
michaelm
parents: 43788
diff changeset
   275
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   276
    void closeIncoming() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   277
        close(-1);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   278
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   279
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   280
    void close(int error) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   281
        if (stopping)
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   282
            return;
46157
f3c2dcb8d8fe 8181422: ClassCastException in HTTP Client
dfuchs
parents: 45713
diff changeset
   283
        stopping = true;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   284
        System.err.printf("Server connection to %s stopping. %d streams\n",
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   285
            socket.getRemoteSocketAddress().toString(), streams.size());
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   286
        streams.forEach((i, q) -> {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   287
            q.orderlyClose();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   288
        });
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   289
        try {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   290
            if (error != -1)
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   291
                goAway(error);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   292
            outputQ.orderlyClose();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   293
            socket.close();
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   294
        } catch (Exception e) {
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   295
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   296
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   297
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   298
    private void readPreface() throws IOException {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   299
        int len = clientPreface.length;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   300
        byte[] bytes = new byte[len];
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   301
        is.readNBytes(bytes, 0, len);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   302
        if (Arrays.compare(clientPreface, bytes) != 0) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   303
            throw new IOException("Invalid preface: " + new String(bytes, 0, len));
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   304
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   305
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   306
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   307
    Http1InitialRequest doUpgrade() throws IOException {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   308
        Http1InitialRequest upgrade = readHttp1Request();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   309
        String h2c = getHeader(upgrade.headers, "Upgrade");
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   310
        if (h2c == null || !h2c.equals("h2c")) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   311
            System.err.println("Server:HEADERS: " + upgrade);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   312
            throw new IOException("Bad upgrade 1 " + h2c);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   313
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   314
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   315
        sendHttp1Response(101, "Switching Protocols", "Connection", "Upgrade",
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   316
                "Upgrade", "h2c");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   317
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   318
        sendSettingsFrame();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   319
        readPreface();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   320
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   321
        String clientSettingsString = getHeader(upgrade.headers, "HTTP2-Settings");
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   322
        clientSettings = getSettingsFromString(clientSettingsString);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   323
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   324
        return upgrade;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   325
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   326
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   327
    /**
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   328
     * Decodes the given, Client, settings payload provided in base64 HTTP1
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   329
     * header value.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   330
     */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   331
    private SettingsFrame getSettingsFromString(String s) throws IOException {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   332
        Base64.Decoder decoder = Base64.getUrlDecoder();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   333
        byte[] payload = decoder.decode(s);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   334
        ByteBuffer bb1 = ByteBuffer.wrap(payload);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   335
        // simulate header of Settings Frame
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   336
        ByteBuffer bb0 = ByteBuffer.wrap(
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   337
                new byte[] {0, 0, (byte)payload.length, 4, 0, 0, 0, 0, 0});
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   338
        List<Http2Frame> frames = new ArrayList<>();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   339
        FramesDecoder reader = new FramesDecoder(frames::add);
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   340
        reader.decode(bb0);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   341
        reader.decode(bb1);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   342
        if (frames.size()!=1)
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   343
            throw new IOException("Expected 1 frame got "+frames.size()) ;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   344
        Http2Frame frame = frames.get(0);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   345
        if (!(frame instanceof SettingsFrame))
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   346
            throw new IOException("Expected SettingsFrame");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   347
        return (SettingsFrame)frame;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   348
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   349
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   350
    public int getMaxFrameSize() {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   351
        return clientSettings.getParameter(SettingsFrame.MAX_FRAME_SIZE);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   352
    }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   353
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   354
    void run() throws Exception {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   355
        Http1InitialRequest upgrade = null;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   356
        if (!secure) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   357
            upgrade = doUpgrade();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   358
        } else {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   359
            readPreface();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   360
            sendSettingsFrame(true);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   361
            clientSettings = (SettingsFrame) readFrame();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   362
            if (clientSettings.getFlag(SettingsFrame.ACK)) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   363
                // we received the ack to our frame first
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   364
                clientSettings = (SettingsFrame) readFrame();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   365
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   366
            nextstream = 1;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   367
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   368
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   369
        // Uncomment if needed, but very noisy
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   370
        //System.out.println("ServerSettings: " + serverSettings);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   371
        //System.out.println("ClientSettings: " + clientSettings);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   372
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   373
        hpackOut = new Encoder(serverSettings.getParameter(HEADER_TABLE_SIZE));
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   374
        hpackIn = new Decoder(clientSettings.getParameter(HEADER_TABLE_SIZE));
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   375
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   376
        if (!secure) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   377
            createPrimordialStream(upgrade);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   378
            nextstream = 3;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   379
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   380
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   381
        (new ConnectionThread("readLoop", this::readLoop)).start();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   382
        (new ConnectionThread("writeLoop", this::writeLoop)).start();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   383
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   384
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   385
    class ConnectionThread extends Thread {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   386
        final Runnable r;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   387
        ConnectionThread(String name, Runnable r) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   388
            setName(name);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   389
            setDaemon(true);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   390
            this.r = r;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   391
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   392
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   393
        public void run() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   394
            r.run();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   395
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   396
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   397
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   398
    private void writeFrame(Http2Frame frame) throws IOException {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   399
        List<ByteBuffer> bufs = new FramesEncoder().encodeFrame(frame);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   400
        //System.err.println("TestServer: Writing frame " + frame.toString());
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   401
        int c = 0;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   402
        for (ByteBuffer buf : bufs) {
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   403
            byte[] ba = buf.array();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   404
            int start = buf.arrayOffset() + buf.position();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   405
            c += buf.remaining();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   406
            os.write(ba, start, buf.remaining());
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   407
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   408
//            System.out.println("writing byte at a time");
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   409
//            while (buf.hasRemaining()) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   410
//                byte b = buf.get();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   411
//                os.write(b);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   412
//                os.flush();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   413
//                try {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   414
//                    Thread.sleep(1);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   415
//                } catch(InterruptedException e) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   416
//                    UncheckedIOException uie = new UncheckedIOException(new IOException(""));
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   417
//                    uie.addSuppressed(e);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   418
//                    throw uie;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   419
//                }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   420
//            }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   421
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   422
        os.flush();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   423
        //System.err.printf("TestServer: wrote %d bytes\n", c);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   424
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   425
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   426
    private void handleCommonFrame(Http2Frame f) throws IOException {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   427
        if (f instanceof SettingsFrame) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   428
            SettingsFrame sf = (SettingsFrame) f;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   429
            if (sf.getFlag(SettingsFrame.ACK)) // ignore
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   430
            {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   431
                return;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   432
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   433
            // otherwise acknowledge it
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   434
            clientSettings = sf;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   435
            SettingsFrame frame = new SettingsFrame();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   436
            frame.setFlag(SettingsFrame.ACK);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   437
            frame.streamid(0);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   438
            outputQ.put(frame);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   439
            return;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   440
        } else if (f instanceof GoAwayFrame) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   441
            System.err.println("Closing: "+ f.toString());
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   442
            close(ErrorFrame.NO_ERROR);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   443
        } else if (f instanceof PingFrame) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   444
            handlePing((PingFrame)f);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   445
        } else
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   446
            throw new UnsupportedOperationException("Not supported yet: " + f.toString());
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   447
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   448
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   449
    void sendWindowUpdates(int len, int streamid) throws IOException {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   450
        if (len == 0)
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   451
            return;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   452
        WindowUpdateFrame wup = new WindowUpdateFrame(streamid, len);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   453
        outputQ.put(wup);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   454
        wup = new WindowUpdateFrame(0 , len);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   455
        outputQ.put(wup);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   456
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   457
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   458
    HttpHeaders decodeHeaders(List<HeaderFrame> frames) throws IOException {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   459
        HttpHeadersBuilder headersBuilder = createNewHeadersBuilder();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   461
        DecodingCallback cb = (name, value) -> {
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   462
            headersBuilder.addHeader(name.toString(), value.toString());
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   463
        };
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   464
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   465
        for (HeaderFrame frame : frames) {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   466
            List<ByteBuffer> buffers = frame.getHeaderBlock();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   467
            for (ByteBuffer buffer : buffers) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   468
                hpackIn.decode(buffer, false, cb);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   469
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   470
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   471
        hpackIn.decode(EMPTY_BUFFER, true, cb);
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   472
        return headersBuilder.build();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   473
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   474
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   475
    String getRequestLine(String request) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   476
        int eol = request.indexOf(CRLF);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   477
        return request.substring(0, eol);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   478
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   479
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   480
    String getHeaders(String request) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   481
        int start = request.indexOf(CRLF);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   482
        int end = request.indexOf(CRLFCRLF);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   483
        if (start == -1 || end == -1) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   484
            throw new RuntimeException("Malformed request");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   485
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   486
        return request.substring(start,end);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   487
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   488
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   489
    static void addHeaders(String headersString, HttpHeadersBuilder headersBuilder) {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   490
        String[] hh = headersString.split(CRLF);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   491
        for (String header : hh) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   492
            int colon = header.indexOf(':');
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   493
            if (colon == -1)
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   494
                continue;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   495
            String name = header.substring(0, colon);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   496
            String value = header.substring(colon+1);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   497
            while (value.startsWith(" "))
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   498
                value = value.substring(1);
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   499
            headersBuilder.addHeader(name, value);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   500
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   501
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   502
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   503
    // First stream (1) comes from a plaintext HTTP/1.1 request
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   504
    @SuppressWarnings({"rawtypes","unchecked"})
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   505
    void createPrimordialStream(Http1InitialRequest request) throws IOException {
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   506
        HttpHeadersBuilder headersBuilder = createNewHeadersBuilder();
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   507
        String requestLine = getRequestLine(request.headers);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   508
        String[] tokens = requestLine.split(" ");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   509
        if (!tokens[2].equals("HTTP/1.1")) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   510
            throw new IOException("bad request line");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   511
        }
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   512
        URI uri;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   513
        try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   514
            uri = new URI(tokens[1]);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   515
        } catch (URISyntaxException e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   516
            throw new IOException(e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   517
        }
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   518
        String host = getHeader(request.headers, "Host");
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   519
        if (host == null) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   520
            throw new IOException("missing Host");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   521
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   522
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   523
        headersBuilder.setHeader(":method", tokens[0]);
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   524
        headersBuilder.setHeader(":scheme", "http"); // always in this case
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   525
        headersBuilder.setHeader(":authority", host);
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   526
        String path = uri.getRawPath();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   527
        if (uri.getRawQuery() != null)
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   528
            path = path + "?" + uri.getRawQuery();
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   529
        headersBuilder.setHeader(":path", path);
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   530
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   531
        Queue q = new Queue(sentinel);
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   532
        byte[] body = getRequestBody(request);
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   533
        addHeaders(getHeaders(request.headers), headersBuilder);
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   534
        headersBuilder.setHeader("Content-length", Integer.toString(body.length));
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   535
        HttpHeaders headers = headersBuilder.build();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   536
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   537
        addRequestBodyToQueue(body, q);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   538
        streams.put(1, q);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   539
        exec.submit(() -> {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   540
            handleRequest(headers, q, 1, true /*complete request has been read*/);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   541
        });
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   542
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   543
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   544
    // all other streams created here
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   545
    @SuppressWarnings({"rawtypes","unchecked"})
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   546
    void createStream(HeaderFrame frame) throws IOException {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   547
        List<HeaderFrame> frames = new LinkedList<>();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   548
        frames.add(frame);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   549
        int streamid = frame.streamid();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   550
        if (streamid != nextstream) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   551
            throw new IOException("unexpected stream id");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   552
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   553
        nextstream += 2;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   554
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   555
        boolean endStream = false;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   556
        if (frame.getFlag(HeaderFrame.END_STREAM)) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   557
            endStream = true;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   558
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   559
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   560
        while (!frame.getFlag(HeaderFrame.END_HEADERS)) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   561
            Http2Frame f = readFrame();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   562
            if (!(f instanceof HeaderFrame)) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   563
                handleCommonFrame(f); // should only be error frames
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   564
            } else {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   565
                frame = (HeaderFrame) f;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   566
                if (frame.getFlag(HeaderFrame.END_STREAM)) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   567
                    endStream = true;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   568
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   569
                frames.add(frame);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   570
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   571
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   572
        boolean endStreamReceived = endStream;
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   573
        HttpHeaders headers = decodeHeaders(frames);
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   574
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   575
        // Strict to assert Client correctness. Not all servers are as strict,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   576
        // but some are known to be.
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   577
        Optional<?> disallowedHeader = headers.firstValue("Upgrade");
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   578
        if (disallowedHeader.isPresent()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   579
            throw new IOException("Unexpected Upgrade in headers:" + headers);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   580
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   581
        disallowedHeader = headers.firstValue("HTTP2-Settings");
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   582
        if (disallowedHeader.isPresent())
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   583
            throw new IOException("Unexpected HTTP2-Settings in headers:" + headers);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   584
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   585
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   586
        Queue q = new Queue(sentinel);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   587
        streams.put(streamid, q);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   588
        exec.submit(() -> {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   589
            handleRequest(headers, q, streamid, endStreamReceived);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   590
        });
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   591
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   592
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   593
    // runs in own thread. Handles request from start to finish. Incoming frames
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   594
    // for this stream/request delivered on Q
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   595
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   596
    @SuppressWarnings({"rawtypes","unchecked"})
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   597
    void handleRequest(HttpHeaders headers,
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   598
                       Queue queue,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   599
                       int streamid,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   600
                       boolean endStreamReceived)
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   601
    {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   602
        String method = headers.firstValue(":method").orElse("");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   603
        //System.out.println("method = " + method);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   604
        String path = headers.firstValue(":path").orElse("");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   605
        //System.out.println("path = " + path);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   606
        String scheme = headers.firstValue(":scheme").orElse("");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   607
        //System.out.println("scheme = " + scheme);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   608
        String authority = headers.firstValue(":authority").orElse("");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   609
        //System.out.println("authority = " + authority);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   610
        System.err.printf("TestServer: %s %s\n", method, path);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   611
        int winsize = clientSettings.getParameter(
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   612
                SettingsFrame.INITIAL_WINDOW_SIZE);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   613
        //System.err.println ("Stream window size = " + winsize);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   614
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   615
        final InputStream bis;
43788
22a618ec8268 8174833: java/net/httpclient/http2/BasicTest.java always fails but always report success
dfuchs
parents: 42460
diff changeset
   616
        if (endStreamReceived && queue.size() == 0) {
22a618ec8268 8174833: java/net/httpclient/http2/BasicTest.java always fails but always report success
dfuchs
parents: 42460
diff changeset
   617
            System.err.println("Server: got END_STREAM for stream " + streamid);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   618
            bis = NullInputStream.INSTANCE;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   619
        } else {
43788
22a618ec8268 8174833: java/net/httpclient/http2/BasicTest.java always fails but always report success
dfuchs
parents: 42460
diff changeset
   620
            System.err.println("Server: creating input stream for stream " + streamid);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   621
            bis = new BodyInputStream(queue, streamid, this);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   622
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   623
        try (bis;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   624
             BodyOutputStream bos = new BodyOutputStream(streamid, winsize, this))
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   625
        {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   626
            outStreams.put(streamid, bos);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   627
            String us = scheme + "://" + authority + path;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   628
            URI uri = new URI(us);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   629
            boolean pushAllowed = clientSettings.getParameter(SettingsFrame.ENABLE_PUSH) == 1;
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   630
            HttpHeadersBuilder rspheadersBuilder = createNewHeadersBuilder();
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   631
            Http2TestExchange exchange = exchangeSupplier.get(streamid, method,
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   632
                    headers, rspheadersBuilder, uri, bis, getSSLSession(),
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   633
                    bos, this, pushAllowed);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   634
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   635
            // give to user
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   636
            Http2Handler handler = server.getHandlerFor(uri.getPath());
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   637
            try {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   638
                handler.handle(exchange);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   639
            } catch (IOException closed) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   640
                if (bos.closed) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   641
                    Queue q = streams.get(streamid);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   642
                    if (q != null && (q.isClosed() || q.isClosing())) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   643
                        System.err.println("TestServer: Stream " + streamid + " closed: " + closed);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   644
                        return;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   645
                    }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   646
                }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   647
                throw closed;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   648
            }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   649
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   650
            // everything happens in the exchange from here. Hopefully will
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   651
            // return though.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   652
        } catch (Throwable e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   653
            System.err.println("TestServer: handleRequest exception: " + e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   654
            e.printStackTrace();
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   655
            close(-1);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   656
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   657
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   658
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   659
    protected HttpHeadersBuilder createNewHeadersBuilder() {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   660
        return new HttpHeadersBuilder();
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   661
    }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   662
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   663
    private SSLSession getSSLSession() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   664
        if (! (socket instanceof SSLSocket))
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   665
            return null;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   666
        SSLSocket ssl = (SSLSocket)socket;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   667
        return ssl.getSession();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   668
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   669
    // Runs in own thread
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   670
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   671
    @SuppressWarnings({"rawtypes","unchecked"})
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   672
    void readLoop() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   673
        try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   674
            while (!stopping) {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   675
                Http2Frame frame = readFrameImpl();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   676
                if (frame == null) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   677
                    closeIncoming();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   678
                    return;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   679
                }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   680
                //System.err.printf("TestServer: received frame %s\n", frame);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   681
                int stream = frame.streamid();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   682
                if (stream == 0) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   683
                    if (frame.type() == WindowUpdateFrame.TYPE) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   684
                        WindowUpdateFrame wup = (WindowUpdateFrame) frame;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   685
                        updateConnectionWindow(wup.getUpdate());
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   686
                    } else {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   687
                        // other common frame types
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   688
                        handleCommonFrame(frame);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   689
                    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   690
                } else {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   691
                    Queue q = streams.get(stream);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   692
                    if (frame.type() == HeadersFrame.TYPE) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   693
                        if (q != null) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   694
                            System.err.println("HEADERS frame for existing stream! Error.");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   695
                            // TODO: close connection
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   696
                            continue;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   697
                        } else {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   698
                            createStream((HeadersFrame) frame);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   699
                        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   700
                    } else {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   701
                        if (q == null && !pushStreams.contains(stream)) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   702
                            System.err.printf("Non Headers frame received with"+
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   703
                                    " non existing stream (%d) ", frame.streamid());
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   704
                            System.err.println(frame);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   705
                            continue;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   706
                        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   707
                        if (frame.type() == WindowUpdateFrame.TYPE) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   708
                            WindowUpdateFrame wup = (WindowUpdateFrame) frame;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   709
                            synchronized (updaters) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   710
                                Consumer<Integer> r = updaters.get(stream);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   711
                                r.accept(wup.getUpdate());
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   712
                            }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   713
                        } else if (frame.type() == ResetFrame.TYPE) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   714
                            // do orderly close on input q
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   715
                            // and close the output q immediately
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   716
                            // This should mean depending on what the
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   717
                            // handler is doing: either an EOF on read
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   718
                            // or an IOException if writing the response.
48523
b95b08f3e1a8 8194883: Unhandleable Push Promises should be cancelled
chegar
parents: 48083
diff changeset
   719
                            if (q != null) {
b95b08f3e1a8 8194883: Unhandleable Push Promises should be cancelled
chegar
parents: 48083
diff changeset
   720
                                q.orderlyClose();
b95b08f3e1a8 8194883: Unhandleable Push Promises should be cancelled
chegar
parents: 48083
diff changeset
   721
                                BodyOutputStream oq = outStreams.get(stream);
b95b08f3e1a8 8194883: Unhandleable Push Promises should be cancelled
chegar
parents: 48083
diff changeset
   722
                                if (oq != null)
b95b08f3e1a8 8194883: Unhandleable Push Promises should be cancelled
chegar
parents: 48083
diff changeset
   723
                                    oq.closeInternal();
b95b08f3e1a8 8194883: Unhandleable Push Promises should be cancelled
chegar
parents: 48083
diff changeset
   724
                            } else if (pushStreams.contains(stream)) {
b95b08f3e1a8 8194883: Unhandleable Push Promises should be cancelled
chegar
parents: 48083
diff changeset
   725
                                // we could interrupt the pushStream's output
b95b08f3e1a8 8194883: Unhandleable Push Promises should be cancelled
chegar
parents: 48083
diff changeset
   726
                                // but the continuation, even after a reset
b95b08f3e1a8 8194883: Unhandleable Push Promises should be cancelled
chegar
parents: 48083
diff changeset
   727
                                // should be handle gracefully by the client
b95b08f3e1a8 8194883: Unhandleable Push Promises should be cancelled
chegar
parents: 48083
diff changeset
   728
                                // anyway.
b95b08f3e1a8 8194883: Unhandleable Push Promises should be cancelled
chegar
parents: 48083
diff changeset
   729
                            } else {
b95b08f3e1a8 8194883: Unhandleable Push Promises should be cancelled
chegar
parents: 48083
diff changeset
   730
                                System.err.println("TestServer: Unexpected frame on: " + stream);
b95b08f3e1a8 8194883: Unhandleable Push Promises should be cancelled
chegar
parents: 48083
diff changeset
   731
                                System.err.println(frame);
b95b08f3e1a8 8194883: Unhandleable Push Promises should be cancelled
chegar
parents: 48083
diff changeset
   732
                                throw new IOException("Unexpected frame");
b95b08f3e1a8 8194883: Unhandleable Push Promises should be cancelled
chegar
parents: 48083
diff changeset
   733
                            }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   734
                        } else {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   735
                            q.put(frame);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   736
                        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   737
                    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   738
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   739
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   740
        } catch (Throwable e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   741
            if (!stopping) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   742
                System.err.println("Http server reader thread shutdown");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   743
                e.printStackTrace();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   744
            }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   745
            close(ErrorFrame.PROTOCOL_ERROR);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   746
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   747
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   748
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   749
    /** Encodes an group of headers, without any ordering guarantees. */
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   750
    List<ByteBuffer> encodeHeaders(HttpHeaders headers) {
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   751
        List<ByteBuffer> buffers = new LinkedList<>();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   752
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   753
        ByteBuffer buf = getBuffer();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   754
        boolean encoded;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   755
        for (Map.Entry<String, List<String>> entry : headers.map().entrySet()) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   756
            List<String> values = entry.getValue();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   757
            String key = entry.getKey().toLowerCase();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   758
            for (String value : values) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   759
                do {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   760
                    hpackOut.header(key, value);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   761
                    encoded = hpackOut.encode(buf);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   762
                    if (!encoded) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   763
                        buf.flip();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   764
                        buffers.add(buf);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   765
                        buf = getBuffer();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   766
                    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   767
                } while (!encoded);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   768
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   769
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   770
        buf.flip();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   771
        buffers.add(buf);
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   772
        return buffers;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   773
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   774
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   775
    /** Encodes an ordered list of headers. */
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   776
    List<ByteBuffer> encodeHeadersOrdered(List<Map.Entry<String,String>> headers) {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   777
        List<ByteBuffer> buffers = new LinkedList<>();
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   778
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   779
        ByteBuffer buf = getBuffer();
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   780
        boolean encoded;
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   781
        for (Map.Entry<String, String> entry : headers) {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   782
            String value = entry.getValue();
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   783
            String key = entry.getKey().toLowerCase();
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   784
            do {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   785
                hpackOut.header(key, value);
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   786
                encoded = hpackOut.encode(buf);
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   787
                if (!encoded) {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   788
                    buf.flip();
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   789
                    buffers.add(buf);
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   790
                    buf = getBuffer();
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   791
                }
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   792
            } while (!encoded);
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   793
        }
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   794
        buf.flip();
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   795
        buffers.add(buf);
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   796
        return buffers;
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   797
    }
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   798
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   799
    static void closeIgnore(Closeable c) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   800
        try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   801
            c.close();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   802
        } catch (IOException e) {}
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   803
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   804
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   805
    // Runs in own thread
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   806
    void writeLoop() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   807
        try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   808
            while (!stopping) {
46157
f3c2dcb8d8fe 8181422: ClassCastException in HTTP Client
dfuchs
parents: 45713
diff changeset
   809
                Http2Frame frame;
f3c2dcb8d8fe 8181422: ClassCastException in HTTP Client
dfuchs
parents: 45713
diff changeset
   810
                try {
f3c2dcb8d8fe 8181422: ClassCastException in HTTP Client
dfuchs
parents: 45713
diff changeset
   811
                    frame = outputQ.take();
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   812
                    if (stopping)
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   813
                        break;
46157
f3c2dcb8d8fe 8181422: ClassCastException in HTTP Client
dfuchs
parents: 45713
diff changeset
   814
                } catch(IOException x) {
f3c2dcb8d8fe 8181422: ClassCastException in HTTP Client
dfuchs
parents: 45713
diff changeset
   815
                    if (stopping && x.getCause() instanceof InterruptedException) {
f3c2dcb8d8fe 8181422: ClassCastException in HTTP Client
dfuchs
parents: 45713
diff changeset
   816
                        break;
f3c2dcb8d8fe 8181422: ClassCastException in HTTP Client
dfuchs
parents: 45713
diff changeset
   817
                    } else throw x;
f3c2dcb8d8fe 8181422: ClassCastException in HTTP Client
dfuchs
parents: 45713
diff changeset
   818
                }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   819
                if (frame instanceof ResponseHeaders) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   820
                    ResponseHeaders rh = (ResponseHeaders)frame;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   821
                    HeadersFrame hf = new HeadersFrame(rh.streamid(), rh.getFlags(), encodeHeaders(rh.headers));
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   822
                    writeFrame(hf);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   823
                } else if (frame instanceof OutgoingPushPromise) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   824
                    handlePush((OutgoingPushPromise)frame);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   825
                } else
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   826
                    writeFrame(frame);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   827
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   828
            System.err.println("TestServer: Connection writer stopping");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   829
        } catch (Throwable e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   830
            e.printStackTrace();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   831
            /*close();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   832
            if (!stopping) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   833
                e.printStackTrace();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   834
                System.err.println("TestServer: writeLoop exception: " + e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   835
            }*/
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   836
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   837
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   838
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   839
    private void handlePush(OutgoingPushPromise op) throws IOException {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   840
        int promisedStreamid = nextPushStreamId;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   841
        PushPromiseFrame pp = new PushPromiseFrame(op.parentStream,
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   842
                                                   HeaderFrame.END_HEADERS,
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   843
                                                   promisedStreamid,
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   844
                                                   encodeHeaders(op.headers),
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   845
                                                   0);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   846
        pushStreams.add(promisedStreamid);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   847
        nextPushStreamId += 2;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   848
        pp.streamid(op.parentStream);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   849
        writeFrame(pp);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   850
        final InputStream ii = op.is;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   851
        final BodyOutputStream oo = new BodyOutputStream(
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   852
                promisedStreamid,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   853
                clientSettings.getParameter(
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   854
                        SettingsFrame.INITIAL_WINDOW_SIZE), this);
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   855
        outStreams.put(promisedStreamid, oo);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   856
        oo.goodToGo();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   857
        exec.submit(() -> {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   858
            try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   859
                ResponseHeaders oh = getPushResponse(promisedStreamid);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   860
                outputQ.put(oh);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   861
                ii.transferTo(oo);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   862
            } catch (Throwable ex) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   863
                System.err.printf("TestServer: pushing response error: %s\n",
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   864
                        ex.toString());
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   865
            } finally {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   866
                closeIgnore(ii);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   867
                closeIgnore(oo);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   868
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   869
        });
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   870
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   871
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   872
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   873
    // returns a minimal response with status 200
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   874
    // that is the response to the push promise just sent
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   875
    private ResponseHeaders getPushResponse(int streamid) {
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   876
        HttpHeadersBuilder hb = createNewHeadersBuilder();
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   877
        hb.addHeader(":status", "200");
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
   878
        ResponseHeaders oh = new ResponseHeaders(hb.build());
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   879
        oh.streamid(streamid);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   880
        oh.setFlag(HeaderFrame.END_HEADERS);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   881
        return oh;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   882
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   883
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   884
    private ByteBuffer getBuffer() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   885
        return ByteBuffer.allocate(8 * 1024);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   886
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   887
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   888
    private Http2Frame readFrame() throws IOException {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   889
        Http2Frame f = readFrameImpl();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   890
        if (f == null)
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   891
            throw new IOException("connection closed");
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   892
        return f;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   893
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   894
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   895
    // does not throw an exception for EOF
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   896
    private Http2Frame readFrameImpl() throws IOException {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   897
        try {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   898
            byte[] buf = new byte[9];
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   899
            int ret;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   900
            ret=is.readNBytes(buf, 0, 9);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   901
            if (ret == 0) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   902
                return null;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   903
            } else if (ret != 9) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   904
                throw new IOException("readFrame: connection closed");
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   905
            }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   906
            int len = 0;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   907
            for (int i = 0; i < 3; i++) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   908
                int n = buf[i] & 0xff;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   909
                //System.err.println("n = " + n);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   910
                len = (len << 8) + n;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   911
            }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   912
            byte[] rest = new byte[len];
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   913
            int n = is.readNBytes(rest, 0, len);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   914
            if (n != len)
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   915
                throw new IOException("Error reading frame");
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   916
            List<Http2Frame> frames = new ArrayList<>();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   917
            FramesDecoder reader = new FramesDecoder(frames::add);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   918
            reader.decode(ByteBuffer.wrap(buf));
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   919
            reader.decode(ByteBuffer.wrap(rest));
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   920
            if (frames.size()!=1)
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   921
                throw new IOException("Expected 1 frame got "+frames.size()) ;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   922
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   923
            return frames.get(0);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   924
        } catch (IOException ee) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   925
            if (stopping)
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   926
                return null;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   927
            throw ee;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   928
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   929
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   930
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   931
    void sendSettingsFrame() throws IOException {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   932
        sendSettingsFrame(false);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   933
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   934
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   935
    void sendSettingsFrame(boolean now) throws IOException {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   936
        if (now) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   937
            writeFrame(serverSettings);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   938
        } else {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   939
            outputQ.put(serverSettings);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   940
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   941
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   942
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   943
    String readUntil(String end) throws IOException {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   944
        int number = end.length();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   945
        int found = 0;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   946
        StringBuilder sb = new StringBuilder();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   947
        while (found < number) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   948
            char expected = end.charAt(found);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   949
            int c = is.read();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   950
            if (c == -1) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   951
                throw new IOException("Connection closed");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   952
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   953
            char c0 = (char) c;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   954
            sb.append(c0);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   955
            if (c0 != expected) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   956
                found = 0;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   957
                continue;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   958
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   959
            found++;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   960
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   961
        return sb.toString();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   962
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   963
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   964
    private int getContentLength(String headers) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   965
        return getIntHeader(headers, "Content-length");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   966
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   967
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   968
    private int getIntHeader(String headers, String name) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   969
        String val = getHeader(headers, name);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   970
        if (val == null) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   971
            return -1;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   972
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   973
        return Integer.parseInt(val);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   974
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   975
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   976
    private String getHeader(String headers, String name) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   977
        String headers1 = headers.toLowerCase(); // not efficient
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   978
        name = CRLF + name.toLowerCase();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   979
        int start = headers1.indexOf(name);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   980
        if (start == -1) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   981
            return null;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   982
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   983
        start += 2;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   984
        int end = headers1.indexOf(CRLF, start);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   985
        String line = headers.substring(start, end);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   986
        start = line.indexOf(':');
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   987
        if (start == -1) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   988
            return null;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   989
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   990
        return line.substring(start + 1).trim();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   991
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   992
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   993
    final static String CRLF = "\r\n";
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   994
    final static String CRLFCRLF = "\r\n\r\n";
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   995
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   996
    static class Http1InitialRequest {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   997
        final String headers;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   998
        final byte[] body;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
   999
        Http1InitialRequest(String headers, byte[] body) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
  1000
            this.headers = headers;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
  1001
            this.body = body.clone();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
  1002
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
  1003
    }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
  1004
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
  1005
    Http1InitialRequest readHttp1Request() throws IOException {
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1006
        String headers = readUntil(CRLF + CRLF);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1007
        int clen = getContentLength(headers);
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1008
        String te = getHeader(headers, "Transfer-encoding");
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1009
        byte[] buf = new byte[0];
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1010
        try {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1011
            if (clen >= 0) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1012
                // HTTP/1.1 fixed length content ( may be 0 ), read it
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1013
                buf = new byte[clen];
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1014
                is.readNBytes(buf, 0, clen);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1015
            } else if ("chunked".equalsIgnoreCase(te)) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1016
                //  HTTP/1.1 chunked data, read it
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1017
                buf = readChunkedInputStream(is);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1018
            }
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
  1019
            return new Http1InitialRequest(headers, buf);
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1020
        } catch (IOException e) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1021
            System.err.println("TestServer: headers read: [ " + headers + " ]");
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1022
            throw e;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1023
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1024
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1025
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1026
    // This is a quick hack to get a chunked input stream reader.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1027
    private static byte[] readChunkedInputStream(InputStream is) throws IOException {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1028
        ChunkedInputStream cis = new ChunkedInputStream(is, new HttpClient() {}, null);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1029
        return cis.readAllBytes();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1030
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1031
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1032
    void sendHttp1Response(int code, String msg, String... headers) throws IOException {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1033
        StringBuilder sb = new StringBuilder();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1034
        sb.append("HTTP/1.1 ")
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1035
                .append(code)
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1036
                .append(' ')
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1037
                .append(msg)
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1038
                .append(CRLF);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1039
        int numheaders = headers.length;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1040
        for (int i = 0; i < numheaders; i += 2) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1041
            sb.append(headers[i])
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1042
                    .append(": ")
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1043
                    .append(headers[i + 1])
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1044
                    .append(CRLF);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1045
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1046
        sb.append(CRLF);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1047
        String s = sb.toString();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1048
        os.write(s.getBytes("US-ASCII"));
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1049
        os.flush();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1050
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1051
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1052
    private void unexpectedFrame(Http2Frame frame) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1053
        System.err.println("OOPS. Unexpected");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1054
        assert false;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1055
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1056
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1057
    final static ByteBuffer[] bbarray = new ByteBuffer[0];
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1058
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1059
    // wrapper around a BlockingQueue that throws an exception when it's closed
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1060
    // Each stream has one of these
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1061
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
  1062
    byte[] getRequestBody(Http1InitialRequest request) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
  1063
        return request.body;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1064
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1065
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1066
    @SuppressWarnings({"rawtypes","unchecked"})
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
  1067
    void addRequestBodyToQueue(byte[] body, Queue q) throws IOException {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48523
diff changeset
  1068
        ByteBuffer buf = ByteBuffer.wrap(body);
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1069
        DataFrame df = new DataFrame(1, DataFrame.END_STREAM, buf);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1070
        // only used for primordial stream
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1071
        q.put(df);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1072
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1073
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1074
    // window updates done in main reader thread because they may
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1075
    // be used to unblock BodyOutputStreams waiting for WUPs
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1076
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1077
    HashMap<Integer,Consumer<Integer>> updaters = new HashMap<>();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1078
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1079
    void registerStreamWindowUpdater(int streamid, Consumer<Integer> r) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1080
        synchronized(updaters) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1081
            updaters.put(streamid, r);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1082
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1083
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1084
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1085
    int sendWindow = 64 * 1024 - 1; // connection level send window
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1086
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1087
    /**
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1088
     * BodyOutputStreams call this to get the connection window first.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1089
     *
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1090
     * @param amount
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1091
     */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1092
    synchronized void obtainConnectionWindow(int amount) throws InterruptedException {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1093
        while (amount > 0) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1094
            int n = Math.min(amount, sendWindow);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1095
            amount -= n;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1096
            sendWindow -= n;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1097
            if (amount > 0)
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1098
                wait();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1099
        }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1100
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1101
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1102
    synchronized void updateConnectionWindow(int amount) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1103
        sendWindow += amount;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1104
        notifyAll();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1105
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1106
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1107
    // simplified output headers class. really just a type safe container
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1108
    // for the hashmap.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1109
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1110
    static class ResponseHeaders extends Http2Frame {
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
  1111
        HttpHeaders headers;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1112
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49765
diff changeset
  1113
        ResponseHeaders(HttpHeaders headers) {
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1114
            super(0, 0);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1115
            this.headers = headers;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1116
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1117
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1118
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1119
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1120
    static class NullInputStream extends InputStream {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1121
        static final NullInputStream INSTANCE = new NullInputStream();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1122
        private NullInputStream() {}
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1123
        public int read()      { return -1; }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1124
        public int available() { return 0;  }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1125
    }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1126
}