src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/websocket/WebSocketImpl.java
author dfuchs
Thu, 16 Nov 2017 19:56:44 +0000
branchhttp-client-branch
changeset 55821 fa0fc03c0853
parent 55805 371ed971281e
child 55824 b922df193260
permissions -rw-r--r--
http-client-branch: HttpClient uses ProxySelector.getDefault() by default
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
/*
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
     2
 * Copyright (c) 2015, 2017, 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.  Oracle designates this
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    10
 *
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    11
 * 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
    12
 * 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
    13
 * 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
    14
 * 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
    15
 * accompanied this code).
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    16
 *
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    17
 * 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
    18
 * 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
    19
 * 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
    20
 *
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    21
 * 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
    22
 * 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
    23
 * questions.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    24
 */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    25
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    26
package jdk.incubator.http.internal.websocket;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    27
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    28
import java.io.IOException;
55789
b3562d42f3b1 http-client-impl: use Reference.reachabilityFence to make clear the websokect BuilderImpl must stay strongly referenced until after the WebSocketImpl is created.
dfuchs
parents: 55768
diff changeset
    29
import java.lang.ref.Reference;
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    30
import java.net.InetSocketAddress;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    31
import java.net.ProtocolException;
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    32
import java.net.Proxy;
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    33
import java.net.ProxySelector;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    34
import java.net.URI;
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    35
import java.net.URLPermission;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    36
import java.nio.ByteBuffer;
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    37
import java.util.Collection;
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    38
import java.util.List;
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    39
import java.util.Optional;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    40
import java.util.Queue;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    41
import java.util.concurrent.CompletableFuture;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    42
import java.util.concurrent.CompletionStage;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    43
import java.util.concurrent.ConcurrentLinkedQueue;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    44
import java.util.concurrent.atomic.AtomicBoolean;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    45
import java.util.function.Consumer;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    46
import java.util.function.Function;
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    47
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    48
import jdk.incubator.http.HttpClient;
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    49
import jdk.incubator.http.WebSocket;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    50
import jdk.incubator.http.internal.common.Log;
55768
8674257c75ce http-client-branch: SSLTube should call onSubscribe in the flow
dfuchs
parents: 55764
diff changeset
    51
import jdk.incubator.http.internal.common.MinimalFuture;
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    52
import jdk.incubator.http.internal.common.Pair;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    53
import jdk.incubator.http.internal.common.SequentialScheduler;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    54
import jdk.incubator.http.internal.common.SequentialScheduler.DeferredCompleter;
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    55
import jdk.incubator.http.internal.common.Utils;
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    56
import jdk.incubator.http.internal.websocket.OpeningHandshake.Result;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    57
import jdk.incubator.http.internal.websocket.OutgoingMessage.Binary;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    58
import jdk.incubator.http.internal.websocket.OutgoingMessage.Close;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    59
import jdk.incubator.http.internal.websocket.OutgoingMessage.Context;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    60
import jdk.incubator.http.internal.websocket.OutgoingMessage.Ping;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    61
import jdk.incubator.http.internal.websocket.OutgoingMessage.Pong;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    62
import jdk.incubator.http.internal.websocket.OutgoingMessage.Text;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    63
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    64
import static java.util.Objects.requireNonNull;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    65
import static java.util.concurrent.CompletableFuture.failedFuture;
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    66
import static java.util.stream.Collectors.joining;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    67
import static jdk.incubator.http.internal.common.Pair.pair;
55805
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
    68
import static jdk.incubator.http.internal.common.Utils.permissionForProxy;
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
    69
import static jdk.incubator.http.internal.websocket.StatusCodes.CLOSED_ABNORMALLY;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    70
import static jdk.incubator.http.internal.websocket.StatusCodes.NO_STATUS_CODE;
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
    71
import static jdk.incubator.http.internal.websocket.StatusCodes.isLegalToSendFromClient;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    72
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    73
/*
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    74
 * A WebSocket client.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    75
 */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    76
final class WebSocketImpl implements WebSocket {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    77
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    78
    private final URI uri;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    79
    private final String subprotocol;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    80
    private final RawChannel channel;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    81
    private final Listener listener;
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
    /*
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    84
     * Whether or not Listener.onClose or Listener.onError has been already
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    85
     * invoked. We keep track of this since only one of these methods is invoked
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    86
     * and it is invoked at most once.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    87
     */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    88
    private boolean lastMethodInvoked;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    89
    private final AtomicBoolean outstandingSend = new AtomicBoolean();
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    90
    private final SequentialScheduler sendScheduler;
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
    91
    private final Queue<Pair<OutgoingMessage, CompletableFuture<WebSocket>>>
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
    92
            queue = new ConcurrentLinkedQueue<>();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    93
    private final Context context = new OutgoingMessage.Context();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    94
    private final Transmitter transmitter;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    95
    private final Receiver receiver;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    96
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    97
    /*
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    98
     * Whether or not the WebSocket has been closed. When a WebSocket has been
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    99
     * closed it means that no further messages can be sent or received.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   100
     * A closure can be triggered by:
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   101
     *
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   102
     *   1. abort()
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   103
     *   2. "Failing the WebSocket Connection" (i.e. a fatal error)
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   104
     *   3. Completion of the Closing handshake
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   105
     */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   106
    private final AtomicBoolean closed = new AtomicBoolean();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   107
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   108
    /*
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   109
     * This lock is enforcing sequential ordering of invocations to listener's
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   110
     * methods. It is supposed to be uncontended. The only contention that can
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   111
     * happen is when onOpen, an asynchronous onError (not related to reading
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   112
     * from the channel, e.g. an error from automatic Pong reply) or onClose
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   113
     * (related to abort) happens. Since all of the above are one-shot actions,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   114
     * the said contention is insignificant.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   115
     */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   116
    private final Object lock = new Object();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   117
55768
8674257c75ce http-client-branch: SSLTube should call onSubscribe in the flow
dfuchs
parents: 55764
diff changeset
   118
    private final CompletableFuture<?> closeReceived = new MinimalFuture<>();
8674257c75ce http-client-branch: SSLTube should call onSubscribe in the flow
dfuchs
parents: 55764
diff changeset
   119
    private final CompletableFuture<?> closeSent = new MinimalFuture<>();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   120
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   121
    /**
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   122
     * Returns the proxy for the given URI when sent through the given client,
55805
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   123
     * or {@code null} if none is required or applicable.
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   124
     */
55821
fa0fc03c0853 http-client-branch: HttpClient uses ProxySelector.getDefault() by default
dfuchs
parents: 55805
diff changeset
   125
    private static Proxy proxyFor(Optional<ProxySelector> selector, URI uri) {
fa0fc03c0853 http-client-branch: HttpClient uses ProxySelector.getDefault() by default
dfuchs
parents: 55805
diff changeset
   126
        if (!selector.isPresent()) {
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   127
            return null;
55805
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   128
        }
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   129
        URI requestURI = OpeningHandshake.createRequestURI(uri);  // based on the HTTP scheme
55821
fa0fc03c0853 http-client-branch: HttpClient uses ProxySelector.getDefault() by default
dfuchs
parents: 55805
diff changeset
   130
        List<Proxy> pl = selector.get().select(requestURI);
55805
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   131
        if (pl.isEmpty()) {
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   132
            return null;
55805
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   133
        }
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   134
        Proxy proxy = pl.get(0);
55805
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   135
        if (proxy.type() != Proxy.Type.HTTP) {
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   136
            return null;
55805
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   137
        }
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   138
        return proxy;
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   139
    }
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   140
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   141
    /**
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   142
     * Performs the necessary security permissions checks to connect ( possibly
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   143
     * through a proxy ) to the builders WebSocket URI.
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   144
     *
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   145
     * @throws SecurityException if the security manager denies access
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   146
     */
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   147
    static void checkPermissions(BuilderImpl b, Proxy proxy) {
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   148
        SecurityManager sm = System.getSecurityManager();
55805
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   149
        if (sm == null) {
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   150
            return;
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   151
        }
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   152
        URLPermission perm1 = Utils.permissionForServer(
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   153
                b.getUri(), "", b.getHeaders().stream().map(p -> p.first).distinct());
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   154
        sm.checkPermission(perm1);
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   155
        if (proxy == null) {
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   156
            return;
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   157
        }
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   158
        URLPermission perm2 = permissionForProxy((InetSocketAddress) proxy.address());
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   159
        if (perm2 != null) {
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   160
            sm.checkPermission(perm2);
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   161
        }
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   162
    }
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   163
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   164
    static CompletableFuture<WebSocket> newInstanceAsync(BuilderImpl b) {
55805
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   165
        // TODO: a security issue? TOCTOU: two accesses to b.getURI
55821
fa0fc03c0853 http-client-branch: HttpClient uses ProxySelector.getDefault() by default
dfuchs
parents: 55805
diff changeset
   166
        Proxy proxy = proxyFor(b.proxySelector(), b.getUri());
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   167
        try {
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   168
            checkPermissions(b, proxy);
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   169
        } catch (Throwable throwable) {
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   170
            return failedFuture(throwable);
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   171
        }
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   172
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   173
        Function<Result, WebSocket> newWebSocket = r -> {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   174
            WebSocketImpl ws = new WebSocketImpl(b.getUri(),
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   175
                                                 r.subprotocol,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   176
                                                 r.channel,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   177
                                                 b.getListener());
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   178
            // The order of calls might cause a subtle effects, like CF will be
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   179
            // returned from the buildAsync _after_ onOpen has been signalled.
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   180
            // This means if onOpen is lengthy, it might cause some problems.
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   181
            ws.signalOpen();
55789
b3562d42f3b1 http-client-impl: use Reference.reachabilityFence to make clear the websokect BuilderImpl must stay strongly referenced until after the WebSocketImpl is created.
dfuchs
parents: 55768
diff changeset
   182
            // make sure we don't release the builder until this lambda
b3562d42f3b1 http-client-impl: use Reference.reachabilityFence to make clear the websokect BuilderImpl must stay strongly referenced until after the WebSocketImpl is created.
dfuchs
parents: 55768
diff changeset
   183
            // has been executed. The builder has a strong reference to
b3562d42f3b1 http-client-impl: use Reference.reachabilityFence to make clear the websokect BuilderImpl must stay strongly referenced until after the WebSocketImpl is created.
dfuchs
parents: 55768
diff changeset
   184
            // the HttpClientFacade, and we want to keep that live until
b3562d42f3b1 http-client-impl: use Reference.reachabilityFence to make clear the websokect BuilderImpl must stay strongly referenced until after the WebSocketImpl is created.
dfuchs
parents: 55768
diff changeset
   185
            // after the raw channel is created and passed to WebSocketImpl.
b3562d42f3b1 http-client-impl: use Reference.reachabilityFence to make clear the websokect BuilderImpl must stay strongly referenced until after the WebSocketImpl is created.
dfuchs
parents: 55768
diff changeset
   186
            Reference.reachabilityFence(b);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   187
            return ws;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   188
        };
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   189
        OpeningHandshake h;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   190
        try {
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   191
            h = new OpeningHandshake(b, proxy);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   192
        } catch (IllegalArgumentException e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   193
            return failedFuture(e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   194
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   195
        return h.send().thenApply(newWebSocket);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   196
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   197
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   198
    WebSocketImpl(URI uri,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   199
                  String subprotocol,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   200
                  RawChannel channel,
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   201
                  Listener listener)
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   202
    {
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   203
        this.uri = requireNonNull(uri);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   204
        this.subprotocol = requireNonNull(subprotocol);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   205
        this.channel = requireNonNull(channel);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   206
        this.listener = requireNonNull(listener);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   207
        this.transmitter = new Transmitter(channel);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   208
        this.receiver = new Receiver(messageConsumerOf(listener), channel);
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   209
        this.sendScheduler = new SequentialScheduler(new SendFirstTask());
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   210
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   211
        // Set up the Closing Handshake action
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   212
        CompletableFuture.allOf(closeReceived, closeSent)
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   213
                .whenComplete((result, error) -> {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   214
                    try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   215
                        channel.close();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   216
                    } catch (IOException e) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   217
                        Log.logError(e);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   218
                    } finally {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   219
                        closed.set(true);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   220
                    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   221
                });
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   222
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   223
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   224
    /*
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   225
     * This initialisation is outside of the constructor for the sake of
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   226
     * safe publication.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   227
     */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   228
    private void signalOpen() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   229
        synchronized (lock) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   230
            // TODO: might hold lock longer than needed causing prolonged
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   231
            // contention? substitute lock for ConcurrentLinkedQueue<Runnable>?
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   232
            try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   233
                listener.onOpen(this);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   234
            } catch (Exception e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   235
                signalError(e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   236
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   237
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   238
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   239
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   240
    private void signalError(Throwable error) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   241
        synchronized (lock) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   242
            if (lastMethodInvoked) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   243
                Log.logError(error);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   244
            } else {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   245
                lastMethodInvoked = true;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   246
                receiver.close();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   247
                try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   248
                    listener.onError(this, error);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   249
                } catch (Exception e) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   250
                    Log.logError(e);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   251
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   252
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   253
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   254
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   255
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   256
    /*
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   257
     * Processes a Close event that came from the channel. Invoked at most once.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   258
     */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   259
    private void processClose(int statusCode, String reason) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   260
        receiver.close();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   261
        try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   262
            channel.shutdownInput();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   263
        } catch (IOException e) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   264
            Log.logError(e);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   265
        }
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   266
        boolean alreadyCompleted = !closeReceived.complete(null);
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   267
        if (alreadyCompleted) {
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   268
            // This CF is supposed to be completed only once, the first time a
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   269
            // Close message is received. No further messages are pulled from
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   270
            // the socket.
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   271
            throw new InternalError();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   272
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   273
        int code;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   274
        if (statusCode == NO_STATUS_CODE || statusCode == CLOSED_ABNORMALLY) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   275
            code = NORMAL_CLOSURE;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   276
        } else {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   277
            code = statusCode;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   278
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   279
        CompletionStage<?> readyToClose = signalClose(statusCode, reason);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   280
        if (readyToClose == null) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   281
            readyToClose = CompletableFuture.completedFuture(null);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   282
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   283
        readyToClose.whenComplete((r, error) -> {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   284
            enqueueClose(new Close(code, ""))
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   285
                    .whenComplete((r1, error1) -> {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   286
                        if (error1 != null) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   287
                            Log.logError(error1);
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
                    });
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   290
        });
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   291
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   292
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   293
    /*
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   294
     * Signals a Close event (might not correspond to anything happened on the
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   295
     * channel, e.g. `abort()`).
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
    private CompletionStage<?> signalClose(int statusCode, String reason) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   298
        synchronized (lock) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   299
            if (lastMethodInvoked) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   300
                Log.logTrace("Close: {0}, ''{1}''", statusCode, reason);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   301
            } else {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   302
                lastMethodInvoked = true;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   303
                receiver.close();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   304
                try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   305
                    return listener.onClose(this, statusCode, reason);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   306
                } catch (Exception e) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   307
                    Log.logError(e);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   308
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   309
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   310
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   311
        return null;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   312
    }
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
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   315
    public CompletableFuture<WebSocket> sendText(CharSequence message,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   316
                                                 boolean isLast)
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
        return enqueueExclusively(new Text(message, isLast));
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   319
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   320
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   321
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   322
    public CompletableFuture<WebSocket> sendBinary(ByteBuffer message,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   323
                                                   boolean isLast)
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   324
    {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   325
        return enqueueExclusively(new Binary(message, isLast));
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
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   329
    public CompletableFuture<WebSocket> sendPing(ByteBuffer message) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   330
        return enqueueExclusively(new Ping(message));
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   331
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   332
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   333
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   334
    public CompletableFuture<WebSocket> sendPong(ByteBuffer message) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   335
        return enqueueExclusively(new Pong(message));
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   336
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   337
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   338
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   339
    public CompletableFuture<WebSocket> sendClose(int statusCode,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   340
                                                  String reason) {
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   341
        if (!isLegalToSendFromClient(statusCode)) {
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   342
            return failedFuture(
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   343
                    new IllegalArgumentException("statusCode: " + statusCode));
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   344
        }
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   345
        Close msg;
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   346
        try {
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   347
            msg = new Close(statusCode, reason);
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   348
        } catch (IllegalArgumentException e) {
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   349
            return failedFuture(e);
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   350
        }
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   351
        return enqueueClose(msg);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   352
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   353
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   354
    /*
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   355
     * Sends a Close message with the given contents and then shuts down the
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   356
     * channel for writing since no more messages are expected to be sent after
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   357
     * this. Invoked at most once.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   358
     */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   359
    private CompletableFuture<WebSocket> enqueueClose(Close m) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   360
        return enqueue(m).whenComplete((r, error) -> {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   361
            try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   362
                channel.shutdownOutput();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   363
            } catch (IOException e) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   364
                Log.logError(e);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   365
            }
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   366
            boolean alreadyCompleted = !closeSent.complete(null);
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   367
            if (alreadyCompleted) {
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   368
                // Shouldn't happen as this callback must run at most once
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   369
                throw new InternalError();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   370
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   371
        });
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
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   374
    /*
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   375
     * Accepts the given message into the outgoing queue in a mutually-exclusive
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   376
     * fashion in respect to other messages accepted through this method. No
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   377
     * further messages will be accepted until the returned CompletableFuture
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   378
     * completes. This method is used to enforce "one outstanding send
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   379
     * operation" policy.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   380
     */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   381
    private CompletableFuture<WebSocket> enqueueExclusively(OutgoingMessage m)
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   382
    {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   383
        if (closed.get()) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   384
            return failedFuture(new IllegalStateException("Closed"));
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   385
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   386
        if (!outstandingSend.compareAndSet(false, true)) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   387
            return failedFuture(new IllegalStateException("Outstanding send"));
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   388
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   389
        return enqueue(m).whenComplete((r, e) -> outstandingSend.set(false));
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   390
    }
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
    private CompletableFuture<WebSocket> enqueue(OutgoingMessage m) {
55768
8674257c75ce http-client-branch: SSLTube should call onSubscribe in the flow
dfuchs
parents: 55764
diff changeset
   393
        CompletableFuture<WebSocket> cf = new MinimalFuture<>();
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   394
        boolean added = queue.add(pair(m, cf));
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   395
        if (!added) {
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   396
            // The queue is supposed to be unbounded
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   397
            throw new InternalError();
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   398
        }
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   399
        sendScheduler.runOrSchedule();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   400
        return cf;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   401
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   402
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   403
    /*
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   404
     * This is the main sending task. It may be run in different threads,
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   405
     * but never concurrently.
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   406
     */
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   407
    private class SendFirstTask implements SequentialScheduler.RestartableTask {
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   408
        @Override
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   409
        public void run (DeferredCompleter taskCompleter){
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   410
            Pair<OutgoingMessage, CompletableFuture<WebSocket>> p = queue.poll();
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   411
            if (p == null) {
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   412
                taskCompleter.complete();
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   413
                return;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   414
            }
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   415
            OutgoingMessage message = p.first;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   416
            CompletableFuture<WebSocket> cf = p.second;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   417
            try {
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   418
                message.contextualize(context);
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   419
                Consumer<Exception> h = e -> {
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   420
                    if (e == null) {
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   421
                        cf.complete(WebSocketImpl.this);
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   422
                    } else {
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   423
                        cf.completeExceptionally(e);
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   424
                    }
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   425
                    sendScheduler.runOrSchedule();
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   426
                    taskCompleter.complete();
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   427
                };
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   428
                transmitter.send(message, h);
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   429
            } catch (Exception t) {
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   430
                cf.completeExceptionally(t);
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   431
            }
42460
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
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   434
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   435
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   436
    public void request(long n) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   437
        receiver.request(n);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   438
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   439
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   440
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   441
    public String getSubprotocol() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   442
        return subprotocol;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   443
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   444
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   445
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   446
    public boolean isClosed() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   447
        return closed.get();
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
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   450
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   451
    public void abort() throws IOException {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   452
        try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   453
            channel.close();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   454
        } finally {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   455
            closed.set(true);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   456
            signalClose(CLOSED_ABNORMALLY, "");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   457
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   458
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   459
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   460
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   461
    public String toString() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   462
        return super.toString()
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   463
                + "[" + (closed.get() ? "CLOSED" : "OPEN") + "]: " + uri
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   464
                + (!subprotocol.isEmpty() ? ", subprotocol=" + subprotocol : "");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   465
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   466
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   467
    private MessageStreamConsumer messageConsumerOf(Listener listener) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   468
        // Synchronization performed here in every method is not for the sake of
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   469
        // ordering invocations to this consumer, after all they are naturally
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   470
        // ordered in the channel. The reason is to avoid an interference with
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   471
        // any unrelated to the channel calls to onOpen, onClose and onError.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   472
        return new MessageStreamConsumer() {
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
            @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   475
            public void onText(MessagePart part, CharSequence data) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   476
                receiver.acknowledge();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   477
                synchronized (WebSocketImpl.this.lock) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   478
                    try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   479
                        listener.onText(WebSocketImpl.this, data, part);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   480
                    } catch (Exception e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   481
                        signalError(e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   482
                    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   483
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   484
            }
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
            @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   487
            public void onBinary(MessagePart part, ByteBuffer data) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   488
                receiver.acknowledge();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   489
                synchronized (WebSocketImpl.this.lock) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   490
                    try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   491
                        listener.onBinary(WebSocketImpl.this, data.slice(), part);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   492
                    } catch (Exception e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   493
                        signalError(e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   494
                    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   495
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   496
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   497
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   498
            @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   499
            public void onPing(ByteBuffer data) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   500
                receiver.acknowledge();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   501
                // Let's make a full copy of this tiny data. What we want here
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   502
                // is to rule out a possibility the shared data we send might be
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   503
                // corrupted the by processing in the listener.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   504
                ByteBuffer slice = data.slice();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   505
                ByteBuffer copy = ByteBuffer.allocate(data.remaining())
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   506
                        .put(data)
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   507
                        .flip();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   508
                // Non-exclusive send;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   509
                CompletableFuture<WebSocket> pongSent = enqueue(new Pong(copy));
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   510
                pongSent.whenComplete(
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   511
                        (r, error) -> {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   512
                            if (error != null) {
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   513
                                WebSocketImpl.this.signalError(
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   514
                                        Utils.getCompletionCause(error));
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   515
                            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   516
                        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   517
                );
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   518
                synchronized (WebSocketImpl.this.lock) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   519
                    try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   520
                        listener.onPing(WebSocketImpl.this, slice);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   521
                    } catch (Exception e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   522
                        signalError(e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   523
                    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   524
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   525
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   526
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   527
            @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   528
            public void onPong(ByteBuffer data) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   529
                receiver.acknowledge();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   530
                synchronized (WebSocketImpl.this.lock) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   531
                    try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   532
                        listener.onPong(WebSocketImpl.this, data.slice());
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   533
                    } catch (Exception e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   534
                        signalError(e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   535
                    }
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
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   538
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   539
            @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   540
            public void onClose(int statusCode, CharSequence reason) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   541
                receiver.acknowledge();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   542
                processClose(statusCode, reason.toString());
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
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   545
            @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   546
            public void onError(Exception error) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   547
                // An signalError doesn't necessarily mean we must signalClose
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   548
                // the WebSocket. However, if it's something the WebSocket
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   549
                // Specification recognizes as a reason for "Failing the
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   550
                // WebSocket Connection", then we must do so, but BEFORE
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   551
                // notifying the Listener.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   552
                if (!(error instanceof FailWebSocketException)) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   553
                    signalError(error);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   554
                } else {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   555
                    Exception ex = (Exception) new ProtocolException().initCause(error);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   556
                    int code = ((FailWebSocketException) error).getStatusCode();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   557
                    enqueueClose(new Close(code, ""))
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   558
                            .whenComplete((r, e) -> {
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   559
                                if (e != null) {
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   560
                                    ex.addSuppressed(Utils.getCompletionCause(e));
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   561
                                }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   562
                                try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   563
                                    channel.close();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   564
                                } catch (IOException e1) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   565
                                    ex.addSuppressed(e1);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   566
                                } finally {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   567
                                    closed.set(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
                                signalError(ex);
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
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   573
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   574
            @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   575
            public void onComplete() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   576
                processClose(CLOSED_ABNORMALLY, "");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   577
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   578
        };
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   579
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   580
}