src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/websocket/WebSocketImpl.java
author prappo
Fri, 17 Nov 2017 14:04:38 +0300
branchhttp-client-branch
changeset 55826 66b5d6013d85
parent 55824 b922df193260
child 55838 12a64276cc96
permissions -rw-r--r--
http-client-branch: (WebSocket) the builder is immutable now
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.List;
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    38
import java.util.Optional;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    39
import java.util.Queue;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    40
import java.util.concurrent.CompletableFuture;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    41
import java.util.concurrent.CompletionStage;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    42
import java.util.concurrent.ConcurrentLinkedQueue;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    43
import java.util.concurrent.atomic.AtomicBoolean;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    44
import java.util.function.Consumer;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    45
import java.util.function.Function;
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    46
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    47
import jdk.incubator.http.WebSocket;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    48
import jdk.incubator.http.internal.common.Log;
55768
8674257c75ce http-client-branch: SSLTube should call onSubscribe in the flow
dfuchs
parents: 55764
diff changeset
    49
import jdk.incubator.http.internal.common.MinimalFuture;
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    50
import jdk.incubator.http.internal.common.Pair;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    51
import jdk.incubator.http.internal.common.SequentialScheduler;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    52
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
    53
import jdk.incubator.http.internal.common.Utils;
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    54
import jdk.incubator.http.internal.websocket.OpeningHandshake.Result;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    55
import jdk.incubator.http.internal.websocket.OutgoingMessage.Binary;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    56
import jdk.incubator.http.internal.websocket.OutgoingMessage.Close;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    57
import jdk.incubator.http.internal.websocket.OutgoingMessage.Context;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    58
import jdk.incubator.http.internal.websocket.OutgoingMessage.Ping;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    59
import jdk.incubator.http.internal.websocket.OutgoingMessage.Pong;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    60
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
    61
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    62
import static java.util.Objects.requireNonNull;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    63
import static java.util.concurrent.CompletableFuture.failedFuture;
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    64
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
    65
import static jdk.incubator.http.internal.common.Pair.pair;
55805
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
    66
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
    67
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
    68
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
    69
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
    70
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    71
/*
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    72
 * A WebSocket client.
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
final class WebSocketImpl implements WebSocket {
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
    private final URI uri;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    77
    private final String subprotocol;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    78
    private final RawChannel channel;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    79
    private final Listener listener;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    80
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    81
    /*
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    82
     * 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
    83
     * 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
    84
     * 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
    85
     */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    86
    private boolean lastMethodInvoked;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    87
    private final AtomicBoolean outstandingSend = new AtomicBoolean();
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    88
    private final SequentialScheduler sendScheduler;
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
    89
    private final Queue<Pair<OutgoingMessage, CompletableFuture<WebSocket>>>
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
    90
            queue = new ConcurrentLinkedQueue<>();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    91
    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
    92
    private final Transmitter transmitter;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    93
    private final Receiver receiver;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    94
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    95
    /*
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    96
     * 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
    97
     * 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
    98
     * A closure can be triggered by:
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    99
     *
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   100
     *   1. abort()
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   101
     *   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
   102
     *   3. Completion of the Closing handshake
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   103
     */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   104
    private final AtomicBoolean closed = new AtomicBoolean();
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
    /*
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   107
     * 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
   108
     * 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
   109
     * 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
   110
     * 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
   111
     * (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
   112
     * the said contention is insignificant.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   113
     */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   114
    private final Object lock = new Object();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   115
55768
8674257c75ce http-client-branch: SSLTube should call onSubscribe in the flow
dfuchs
parents: 55764
diff changeset
   116
    private final CompletableFuture<?> closeReceived = new MinimalFuture<>();
8674257c75ce http-client-branch: SSLTube should call onSubscribe in the flow
dfuchs
parents: 55764
diff changeset
   117
    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
   118
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   119
    /**
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   120
     * 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
   121
     * 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
   122
     */
55821
fa0fc03c0853 http-client-branch: HttpClient uses ProxySelector.getDefault() by default
dfuchs
parents: 55805
diff changeset
   123
    private static Proxy proxyFor(Optional<ProxySelector> selector, URI uri) {
fa0fc03c0853 http-client-branch: HttpClient uses ProxySelector.getDefault() by default
dfuchs
parents: 55805
diff changeset
   124
        if (!selector.isPresent()) {
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   125
            return null;
55805
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   126
        }
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   127
        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
   128
        List<Proxy> pl = selector.get().select(requestURI);
55805
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   129
        if (pl.isEmpty()) {
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   130
            return null;
55805
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   131
        }
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   132
        Proxy proxy = pl.get(0);
55805
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   133
        if (proxy.type() != Proxy.Type.HTTP) {
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   134
            return null;
55805
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   135
        }
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   136
        return proxy;
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   137
    }
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   138
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
     * 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
   141
     * through a proxy ) to the builders WebSocket URI.
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   142
     *
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   143
     * @throws SecurityException if the security manager denies access
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
    static void checkPermissions(BuilderImpl b, Proxy proxy) {
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   146
        SecurityManager sm = System.getSecurityManager();
55805
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   147
        if (sm == null) {
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   148
            return;
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   149
        }
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   150
        URLPermission perm1 = Utils.permissionForServer(
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   151
                b.getUri(), "", b.getHeaders().stream().map(p -> p.first).distinct());
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   152
        sm.checkPermission(perm1);
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   153
        if (proxy == null) {
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   154
            return;
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   155
        }
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   156
        URLPermission perm2 = permissionForProxy((InetSocketAddress) proxy.address());
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   157
        if (perm2 != null) {
371ed971281e http-client-branch: common URLPermission paths
prappo
parents: 55803
diff changeset
   158
            sm.checkPermission(perm2);
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   159
        }
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   160
    }
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   161
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   162
    static CompletableFuture<WebSocket> newInstanceAsync(BuilderImpl b) {
55826
66b5d6013d85 http-client-branch: (WebSocket) the builder is immutable now
prappo
parents: 55824
diff changeset
   163
        Proxy proxy = proxyFor(b.getProxySelector(), b.getUri());
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   164
        try {
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   165
            checkPermissions(b, proxy);
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   166
        } catch (Throwable throwable) {
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   167
            return failedFuture(throwable);
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   168
        }
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   169
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   170
        Function<Result, WebSocket> newWebSocket = r -> {
55826
66b5d6013d85 http-client-branch: (WebSocket) the builder is immutable now
prappo
parents: 55824
diff changeset
   171
            WebSocketImpl ws = new WebSocketImpl(b.getUri(),
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   172
                                                 r.subprotocol,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   173
                                                 r.channel,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   174
                                                 b.getListener());
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   175
            // 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
   176
            // 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
   177
            // 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
   178
            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
   179
            // 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
   180
            // 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
   181
            // 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
   182
            // 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
   183
            Reference.reachabilityFence(b);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   184
            return ws;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   185
        };
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   186
        OpeningHandshake h;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   187
        try {
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   188
            h = new OpeningHandshake(b, proxy);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   189
        } catch (IllegalArgumentException e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   190
            return failedFuture(e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   191
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   192
        return h.send().thenApply(newWebSocket);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   193
    }
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
    WebSocketImpl(URI uri,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   196
                  String subprotocol,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   197
                  RawChannel channel,
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   198
                  Listener listener)
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   199
    {
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   200
        this.uri = requireNonNull(uri);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   201
        this.subprotocol = requireNonNull(subprotocol);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   202
        this.channel = requireNonNull(channel);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   203
        this.listener = requireNonNull(listener);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   204
        this.transmitter = new Transmitter(channel);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   205
        this.receiver = new Receiver(messageConsumerOf(listener), channel);
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   206
        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
   207
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   208
        // Set up the Closing Handshake action
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   209
        CompletableFuture.allOf(closeReceived, closeSent)
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   210
                .whenComplete((result, error) -> {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   211
                    try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   212
                        channel.close();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   213
                    } catch (IOException e) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   214
                        Log.logError(e);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   215
                    } finally {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   216
                        closed.set(true);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   217
                    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   218
                });
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   219
    }
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
     * 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
   223
     * safe publication.
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
    private void signalOpen() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   226
        synchronized (lock) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   227
            // 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
   228
            // contention? substitute lock for ConcurrentLinkedQueue<Runnable>?
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   229
            try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   230
                listener.onOpen(this);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   231
            } catch (Exception e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   232
                signalError(e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   233
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   234
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   235
    }
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
    private void signalError(Throwable error) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   238
        synchronized (lock) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   239
            if (lastMethodInvoked) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   240
                Log.logError(error);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   241
            } else {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   242
                lastMethodInvoked = true;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   243
                receiver.close();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   244
                try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   245
                    listener.onError(this, error);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   246
                } catch (Exception e) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   247
                    Log.logError(e);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   248
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   249
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   250
        }
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
     * 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
   255
     */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   256
    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
   257
        receiver.close();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   258
        try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   259
            channel.shutdownInput();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   260
        } catch (IOException e) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   261
            Log.logError(e);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   262
        }
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   263
        boolean alreadyCompleted = !closeReceived.complete(null);
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   264
        if (alreadyCompleted) {
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   265
            // 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
   266
            // 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
   267
            // the socket.
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   268
            throw new InternalError();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   269
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   270
        int code;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   271
        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
   272
            code = NORMAL_CLOSURE;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   273
        } else {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   274
            code = statusCode;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   275
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   276
        CompletionStage<?> readyToClose = signalClose(statusCode, reason);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   277
        if (readyToClose == null) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   278
            readyToClose = CompletableFuture.completedFuture(null);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   279
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   280
        readyToClose.whenComplete((r, error) -> {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   281
            enqueueClose(new Close(code, ""))
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   282
                    .whenComplete((r1, error1) -> {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   283
                        if (error1 != null) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   284
                            Log.logError(error1);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   285
                        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   286
                    });
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   287
        });
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
     * 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
   292
     * channel, e.g. `abort()`).
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
    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
   295
        synchronized (lock) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   296
            if (lastMethodInvoked) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   297
                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
   298
            } else {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   299
                lastMethodInvoked = true;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   300
                receiver.close();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   301
                try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   302
                    return listener.onClose(this, statusCode, reason);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   303
                } catch (Exception e) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   304
                    Log.logError(e);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   305
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   306
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   307
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   308
        return null;
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
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   312
    public CompletableFuture<WebSocket> sendText(CharSequence message,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   313
                                                 boolean isLast)
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   314
    {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   315
        return enqueueExclusively(new Text(message, isLast));
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   316
    }
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
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   319
    public CompletableFuture<WebSocket> sendBinary(ByteBuffer message,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   320
                                                   boolean isLast)
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   321
    {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   322
        return enqueueExclusively(new Binary(message, isLast));
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   323
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   324
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   325
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   326
    public CompletableFuture<WebSocket> sendPing(ByteBuffer message) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   327
        return enqueueExclusively(new Ping(message));
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   328
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   329
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   330
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   331
    public CompletableFuture<WebSocket> sendPong(ByteBuffer message) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   332
        return enqueueExclusively(new Pong(message));
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   333
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   334
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   335
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   336
    public CompletableFuture<WebSocket> sendClose(int statusCode,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   337
                                                  String reason) {
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   338
        if (!isLegalToSendFromClient(statusCode)) {
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   339
            return failedFuture(
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   340
                    new IllegalArgumentException("statusCode: " + statusCode));
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   341
        }
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   342
        Close msg;
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   343
        try {
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   344
            msg = new Close(statusCode, reason);
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   345
        } catch (IllegalArgumentException e) {
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   346
            return failedFuture(e);
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   347
        }
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   348
        return enqueueClose(msg);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   349
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   350
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   351
    /*
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   352
     * 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
   353
     * 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
   354
     * this. Invoked at most once.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   355
     */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   356
    private CompletableFuture<WebSocket> enqueueClose(Close m) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   357
        return enqueue(m).whenComplete((r, error) -> {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   358
            try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   359
                channel.shutdownOutput();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   360
            } catch (IOException e) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   361
                Log.logError(e);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   362
            }
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   363
            boolean alreadyCompleted = !closeSent.complete(null);
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   364
            if (alreadyCompleted) {
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   365
                // 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
   366
                throw new InternalError();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   367
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   368
        });
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   369
    }
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
     * 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
   373
     * 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
   374
     * 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
   375
     * 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
   376
     * operation" policy.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   377
     */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   378
    private CompletableFuture<WebSocket> enqueueExclusively(OutgoingMessage m)
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   379
    {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   380
        if (closed.get()) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   381
            return failedFuture(new IllegalStateException("Closed"));
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 (!outstandingSend.compareAndSet(false, true)) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   384
            return failedFuture(new IllegalStateException("Outstanding send"));
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
        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
   387
    }
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
    private CompletableFuture<WebSocket> enqueue(OutgoingMessage m) {
55768
8674257c75ce http-client-branch: SSLTube should call onSubscribe in the flow
dfuchs
parents: 55764
diff changeset
   390
        CompletableFuture<WebSocket> cf = new MinimalFuture<>();
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   391
        boolean added = queue.add(pair(m, cf));
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   392
        if (!added) {
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   393
            // The queue is supposed to be unbounded
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   394
            throw new InternalError();
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   395
        }
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   396
        sendScheduler.runOrSchedule();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   397
        return cf;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   398
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   399
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   400
    /*
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   401
     * 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
   402
     * but never concurrently.
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
    private class SendFirstTask implements SequentialScheduler.RestartableTask {
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   405
        @Override
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   406
        public void run (DeferredCompleter taskCompleter){
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   407
            Pair<OutgoingMessage, CompletableFuture<WebSocket>> p = queue.poll();
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   408
            if (p == null) {
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   409
                taskCompleter.complete();
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   410
                return;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   411
            }
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   412
            OutgoingMessage message = p.first;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   413
            CompletableFuture<WebSocket> cf = p.second;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   414
            try {
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   415
                message.contextualize(context);
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   416
                Consumer<Exception> h = e -> {
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   417
                    if (e == null) {
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   418
                        cf.complete(WebSocketImpl.this);
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   419
                    } else {
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   420
                        cf.completeExceptionally(e);
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   421
                    }
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   422
                    sendScheduler.runOrSchedule();
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   423
                    taskCompleter.complete();
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
                transmitter.send(message, h);
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   426
            } catch (Exception t) {
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   427
                cf.completeExceptionally(t);
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   428
            }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   429
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   430
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   431
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   432
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   433
    public void request(long n) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   434
        receiver.request(n);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   435
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   436
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   437
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   438
    public String getSubprotocol() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   439
        return subprotocol;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   440
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   441
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   442
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   443
    public boolean isClosed() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   444
        return closed.get();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   445
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   446
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   447
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   448
    public void abort() throws IOException {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   449
        try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   450
            channel.close();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   451
        } finally {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   452
            closed.set(true);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   453
            signalClose(CLOSED_ABNORMALLY, "");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   454
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   455
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   456
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   457
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   458
    public String toString() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   459
        return super.toString()
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   460
                + "[" + (closed.get() ? "CLOSED" : "OPEN") + "]: " + uri
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   461
                + (!subprotocol.isEmpty() ? ", subprotocol=" + subprotocol : "");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   462
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   463
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   464
    private MessageStreamConsumer messageConsumerOf(Listener listener) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   465
        // 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
   466
        // 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
   467
        // 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
   468
        // 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
   469
        return new MessageStreamConsumer() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   470
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   471
            @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   472
            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
   473
                receiver.acknowledge();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   474
                synchronized (WebSocketImpl.this.lock) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   475
                    try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   476
                        listener.onText(WebSocketImpl.this, data, part);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   477
                    } catch (Exception e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   478
                        signalError(e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   479
                    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   480
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   481
            }
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
            @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   484
            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
   485
                receiver.acknowledge();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   486
                synchronized (WebSocketImpl.this.lock) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   487
                    try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   488
                        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
   489
                    } catch (Exception e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   490
                        signalError(e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   491
                    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   492
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   493
            }
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
            @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   496
            public void onPing(ByteBuffer data) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   497
                receiver.acknowledge();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   498
                // 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
   499
                // 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
   500
                // 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
   501
                ByteBuffer slice = data.slice();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   502
                ByteBuffer copy = ByteBuffer.allocate(data.remaining())
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   503
                        .put(data)
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   504
                        .flip();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   505
                // Non-exclusive send;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   506
                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
   507
                pongSent.whenComplete(
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   508
                        (r, error) -> {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   509
                            if (error != null) {
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   510
                                WebSocketImpl.this.signalError(
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   511
                                        Utils.getCompletionCause(error));
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   512
                            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   513
                        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   514
                );
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   515
                synchronized (WebSocketImpl.this.lock) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   516
                    try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   517
                        listener.onPing(WebSocketImpl.this, slice);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   518
                    } catch (Exception e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   519
                        signalError(e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   520
                    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   521
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   522
            }
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
            @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   525
            public void onPong(ByteBuffer data) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   526
                receiver.acknowledge();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   527
                synchronized (WebSocketImpl.this.lock) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   528
                    try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   529
                        listener.onPong(WebSocketImpl.this, data.slice());
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   530
                    } catch (Exception e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   531
                        signalError(e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   532
                    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   533
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   534
            }
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
            @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   537
            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
   538
                receiver.acknowledge();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   539
                processClose(statusCode, reason.toString());
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   540
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   541
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   542
            @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   543
            public void onError(Exception error) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   544
                // 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
   545
                // 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
   546
                // 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
   547
                // 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
   548
                // notifying the Listener.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   549
                if (!(error instanceof FailWebSocketException)) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   550
                    signalError(error);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   551
                } else {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   552
                    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
   553
                    int code = ((FailWebSocketException) error).getStatusCode();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   554
                    enqueueClose(new Close(code, ""))
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   555
                            .whenComplete((r, e) -> {
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   556
                                if (e != null) {
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   557
                                    ex.addSuppressed(Utils.getCompletionCause(e));
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   558
                                }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   559
                                try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   560
                                    channel.close();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   561
                                } catch (IOException e1) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   562
                                    ex.addSuppressed(e1);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   563
                                } finally {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   564
                                    closed.set(true);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   565
                                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   566
                                signalError(ex);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   567
                            });
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
            }
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
            @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   572
            public void onComplete() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   573
                processClose(CLOSED_ABNORMALLY, "");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   574
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   575
        };
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   576
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   577
}