src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/websocket/WebSocketImpl.java
author chegar
Sun, 05 Nov 2017 21:19:55 +0000
branchhttp-client-branch
changeset 55764 34d7cc00f87a
parent 55763 634d8e14c172
child 55768 8674257c75ce
permissions -rw-r--r--
http-client-branch: WebSocket permission checks, test updates, and more
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;
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    29
import java.net.InetSocketAddress;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    30
import java.net.ProtocolException;
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    31
import java.net.Proxy;
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    32
import java.net.ProxySelector;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    33
import java.net.URI;
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    34
import java.net.URISyntaxException;
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    35
import java.net.URLPermission;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    36
import java.nio.ByteBuffer;
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    37
import java.util.Collection;
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    38
import java.util.List;
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    39
import java.util.Optional;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    40
import java.util.Queue;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    41
import java.util.concurrent.CompletableFuture;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    42
import java.util.concurrent.CompletionStage;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    43
import java.util.concurrent.ConcurrentLinkedQueue;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    44
import java.util.concurrent.atomic.AtomicBoolean;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    45
import java.util.function.Consumer;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    46
import java.util.function.Function;
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    47
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    48
import jdk.incubator.http.HttpClient;
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    49
import jdk.incubator.http.WebSocket;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    50
import jdk.incubator.http.internal.common.Log;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    51
import jdk.incubator.http.internal.common.Pair;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    52
import jdk.incubator.http.internal.common.SequentialScheduler;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    53
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
    54
import jdk.incubator.http.internal.common.Utils;
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    55
import jdk.incubator.http.internal.websocket.OpeningHandshake.Result;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    56
import jdk.incubator.http.internal.websocket.OutgoingMessage.Binary;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    57
import jdk.incubator.http.internal.websocket.OutgoingMessage.Close;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    58
import jdk.incubator.http.internal.websocket.OutgoingMessage.Context;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    59
import jdk.incubator.http.internal.websocket.OutgoingMessage.Ping;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    60
import jdk.incubator.http.internal.websocket.OutgoingMessage.Pong;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
    61
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
    62
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    63
import static java.util.Objects.requireNonNull;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    64
import static java.util.concurrent.CompletableFuture.failedFuture;
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
    65
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
    66
import static jdk.incubator.http.internal.common.Pair.pair;
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
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   116
    private final CompletableFuture<?> closeReceived = new CompletableFuture<>();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   117
    private final CompletableFuture<?> closeSent = new CompletableFuture<>();
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
    /** Returns the security permission required for the given details. */
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   120
    static URLPermission permissionForServer(URI uri,
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   121
                                             Collection<Pair<String, String>> headers) {
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   122
        StringBuilder sb = new StringBuilder();
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   123
        sb.append(uri.getScheme()).append("://")
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   124
          .append(uri.getAuthority())
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   125
          .append(uri.getPath());
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   126
        String urlstring = sb.toString();
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   127
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   128
        String actionstring = headers.stream()
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   129
                .map(p -> p.first)
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   130
                .distinct()
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   131
                .collect(joining(","));
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   132
        if (actionstring != null && !actionstring.equals(""))
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   133
            actionstring = ":" + actionstring;     // Note: no method in the action string
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   134
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   135
        return new URLPermission(urlstring, actionstring);
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   136
    }
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
     * Returns the security permissions required to connect to the proxy, or
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   140
     * null if none is required or applicable.
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   141
     */
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   142
    static URLPermission permissionForProxy(Proxy proxy) {
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   143
        InetSocketAddress proxyAddress = (InetSocketAddress)proxy.address();
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
        StringBuilder sb = new StringBuilder();
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   146
        sb.append("socket://")
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   147
          .append(proxyAddress.getHostString()).append(":")
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   148
          .append(proxyAddress.getPort());
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   149
        String urlstring = sb.toString();
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   150
        return new URLPermission(urlstring.toString(), "CONNECT");
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   151
    }
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   152
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   153
    /**
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   154
     * Returns the proxy for the given URI when sent through the given client,
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   155
     * or null if none is required or applicable.
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   156
     */
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   157
    static Proxy proxyFor(HttpClient client, URI uri) {
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   158
        Optional<ProxySelector> optional = client.proxy();
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   159
        if (!optional.isPresent())
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   160
            return null;
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   161
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   162
        uri = OpeningHandshake.createRequestURI(uri);  // based on the HTTP scheme
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   163
        List<Proxy> pl = optional.get().select(uri);
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   164
        if (pl.size() < 1)
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   165
            return null;
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   166
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   167
        Proxy proxy = pl.get(0);
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   168
        if (!proxy.type().equals(Proxy.Type.HTTP))
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   169
            return null;
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   170
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   171
        return proxy;
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   172
    }
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   173
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   174
    /**
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   175
     * 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
   176
     * through a proxy ) to the builders WebSocket URI.
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   177
     *
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   178
     * @throws SecurityException if the security manager denies access
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   179
     */
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   180
    static void checkPermissions(BuilderImpl b, Proxy proxy) {
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   181
        SecurityManager sm = System.getSecurityManager();
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   182
        if (sm != null) {
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   183
            sm.checkPermission(permissionForServer(b.getUri(), b.getHeaders()));
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   184
            if (proxy != null) {
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   185
                URLPermission perm = permissionForProxy(proxy);
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   186
                if (perm != null)
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   187
                    sm.checkPermission(perm);
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   188
            }
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   189
        }
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   190
    }
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   191
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   192
    static CompletableFuture<WebSocket> newInstanceAsync(BuilderImpl b) {
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   193
        Proxy proxy = proxyFor(b.getClient(), b.getUri());
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   194
        try {
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   195
            checkPermissions(b, proxy);
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   196
        } catch (Throwable throwable) {
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   197
            return failedFuture(throwable);
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   198
        }
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   199
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   200
        Function<Result, WebSocket> newWebSocket = r -> {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   201
            WebSocketImpl ws = new WebSocketImpl(b.getUri(),
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   202
                                                 r.subprotocol,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   203
                                                 r.channel,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   204
                                                 b.getListener());
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   205
            // 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
   206
            // 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
   207
            // 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
   208
            ws.signalOpen();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   209
            return ws;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   210
        };
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   211
        OpeningHandshake h;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   212
        try {
55764
34d7cc00f87a http-client-branch: WebSocket permission checks, test updates, and more
chegar
parents: 55763
diff changeset
   213
            h = new OpeningHandshake(b, proxy);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   214
        } catch (IllegalArgumentException e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   215
            return failedFuture(e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   216
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   217
        return h.send().thenApply(newWebSocket);
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
    WebSocketImpl(URI uri,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   221
                  String subprotocol,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   222
                  RawChannel channel,
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   223
                  Listener listener)
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   224
    {
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   225
        this.uri = requireNonNull(uri);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   226
        this.subprotocol = requireNonNull(subprotocol);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   227
        this.channel = requireNonNull(channel);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   228
        this.listener = requireNonNull(listener);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   229
        this.transmitter = new Transmitter(channel);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   230
        this.receiver = new Receiver(messageConsumerOf(listener), channel);
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   231
        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
   232
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   233
        // Set up the Closing Handshake action
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   234
        CompletableFuture.allOf(closeReceived, closeSent)
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   235
                .whenComplete((result, error) -> {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   236
                    try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   237
                        channel.close();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   238
                    } catch (IOException e) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   239
                        Log.logError(e);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   240
                    } finally {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   241
                        closed.set(true);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   242
                    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   243
                });
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   244
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   245
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   246
    /*
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   247
     * 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
   248
     * safe publication.
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
    private void signalOpen() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   251
        synchronized (lock) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   252
            // 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
   253
            // contention? substitute lock for ConcurrentLinkedQueue<Runnable>?
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   254
            try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   255
                listener.onOpen(this);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   256
            } catch (Exception e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   257
                signalError(e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   258
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   259
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   260
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   261
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   262
    private void signalError(Throwable error) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   263
        synchronized (lock) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   264
            if (lastMethodInvoked) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   265
                Log.logError(error);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   266
            } else {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   267
                lastMethodInvoked = true;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   268
                receiver.close();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   269
                try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   270
                    listener.onError(this, error);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   271
                } catch (Exception e) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   272
                    Log.logError(e);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   273
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   274
            }
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
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   277
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   278
    /*
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   279
     * 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
   280
     */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   281
    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
   282
        receiver.close();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   283
        try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   284
            channel.shutdownInput();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   285
        } catch (IOException e) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   286
            Log.logError(e);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   287
        }
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   288
        boolean alreadyCompleted = !closeReceived.complete(null);
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   289
        if (alreadyCompleted) {
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   290
            // 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
   291
            // 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
   292
            // the socket.
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   293
            throw new InternalError();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   294
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   295
        int code;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   296
        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
   297
            code = NORMAL_CLOSURE;
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
            code = statusCode;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   300
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   301
        CompletionStage<?> readyToClose = signalClose(statusCode, reason);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   302
        if (readyToClose == null) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   303
            readyToClose = CompletableFuture.completedFuture(null);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   304
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   305
        readyToClose.whenComplete((r, error) -> {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   306
            enqueueClose(new Close(code, ""))
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   307
                    .whenComplete((r1, error1) -> {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   308
                        if (error1 != null) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   309
                            Log.logError(error1);
42460
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
                    });
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   312
        });
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   313
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   314
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   315
    /*
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   316
     * 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
   317
     * channel, e.g. `abort()`).
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   318
     */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   319
    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
   320
        synchronized (lock) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   321
            if (lastMethodInvoked) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   322
                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
   323
            } else {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   324
                lastMethodInvoked = true;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   325
                receiver.close();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   326
                try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   327
                    return listener.onClose(this, statusCode, reason);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   328
                } catch (Exception e) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   329
                    Log.logError(e);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   330
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   331
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   332
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   333
        return null;
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
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   336
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   337
    public CompletableFuture<WebSocket> sendText(CharSequence message,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   338
                                                 boolean isLast)
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   339
    {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   340
        return enqueueExclusively(new Text(message, isLast));
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   341
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   342
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   343
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   344
    public CompletableFuture<WebSocket> sendBinary(ByteBuffer message,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   345
                                                   boolean isLast)
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   346
    {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   347
        return enqueueExclusively(new Binary(message, isLast));
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   348
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   349
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   350
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   351
    public CompletableFuture<WebSocket> sendPing(ByteBuffer message) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   352
        return enqueueExclusively(new Ping(message));
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   353
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   354
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   355
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   356
    public CompletableFuture<WebSocket> sendPong(ByteBuffer message) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   357
        return enqueueExclusively(new Pong(message));
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   358
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   359
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   360
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   361
    public CompletableFuture<WebSocket> sendClose(int statusCode,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   362
                                                  String reason) {
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   363
        if (!isLegalToSendFromClient(statusCode)) {
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   364
            return failedFuture(
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   365
                    new IllegalArgumentException("statusCode: " + statusCode));
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   366
        }
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   367
        Close msg;
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   368
        try {
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   369
            msg = new Close(statusCode, reason);
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   370
        } catch (IllegalArgumentException e) {
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   371
            return failedFuture(e);
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   372
        }
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   373
        return enqueueClose(msg);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   374
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   375
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   376
    /*
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   377
     * 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
   378
     * 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
   379
     * this. Invoked at most once.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   380
     */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   381
    private CompletableFuture<WebSocket> enqueueClose(Close m) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   382
        return enqueue(m).whenComplete((r, error) -> {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   383
            try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   384
                channel.shutdownOutput();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   385
            } catch (IOException e) {
43730
b6847c320451 8174745: Httpclient source update for JDK 8
michaelm
parents: 42460
diff changeset
   386
                Log.logError(e);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   387
            }
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   388
            boolean alreadyCompleted = !closeSent.complete(null);
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   389
            if (alreadyCompleted) {
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   390
                // 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
   391
                throw new InternalError();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   392
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   393
        });
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   394
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   395
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   396
    /*
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   397
     * 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
   398
     * 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
   399
     * 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
   400
     * 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
   401
     * operation" policy.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   402
     */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   403
    private CompletableFuture<WebSocket> enqueueExclusively(OutgoingMessage m)
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   404
    {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   405
        if (closed.get()) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   406
            return failedFuture(new IllegalStateException("Closed"));
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   407
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   408
        if (!outstandingSend.compareAndSet(false, true)) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   409
            return failedFuture(new IllegalStateException("Outstanding send"));
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   410
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   411
        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
   412
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   413
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   414
    private CompletableFuture<WebSocket> enqueue(OutgoingMessage m) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   415
        CompletableFuture<WebSocket> cf = new CompletableFuture<>();
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   416
        boolean added = queue.add(pair(m, cf));
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   417
        if (!added) {
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   418
            // The queue is supposed to be unbounded
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   419
            throw new InternalError();
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   420
        }
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   421
        sendScheduler.runOrSchedule();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   422
        return cf;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   423
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   424
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   425
    /*
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   426
     * 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
   427
     * but never concurrently.
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   428
     */
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   429
    private class SendFirstTask implements SequentialScheduler.RestartableTask {
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   430
        @Override
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   431
        public void run (DeferredCompleter taskCompleter){
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   432
            Pair<OutgoingMessage, CompletableFuture<WebSocket>> p = queue.poll();
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   433
            if (p == null) {
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   434
                taskCompleter.complete();
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   435
                return;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   436
            }
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   437
            OutgoingMessage message = p.first;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   438
            CompletableFuture<WebSocket> cf = p.second;
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   439
            try {
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   440
                message.contextualize(context);
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   441
                Consumer<Exception> h = e -> {
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   442
                    if (e == null) {
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   443
                        cf.complete(WebSocketImpl.this);
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   444
                    } else {
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   445
                        cf.completeExceptionally(e);
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   446
                    }
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   447
                    sendScheduler.runOrSchedule();
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   448
                    taskCompleter.complete();
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   449
                };
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   450
                transmitter.send(message, h);
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   451
            } catch (Exception t) {
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   452
                cf.completeExceptionally(t);
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   453
            }
42460
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 void request(long n) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   459
        receiver.request(n);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   460
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   461
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   462
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   463
    public String getSubprotocol() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   464
        return subprotocol;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   465
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   466
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   467
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   468
    public boolean isClosed() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   469
        return closed.get();
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
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   472
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   473
    public void abort() throws IOException {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   474
        try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   475
            channel.close();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   476
        } finally {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   477
            closed.set(true);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   478
            signalClose(CLOSED_ABNORMALLY, "");
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
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   483
    public String toString() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   484
        return super.toString()
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   485
                + "[" + (closed.get() ? "CLOSED" : "OPEN") + "]: " + uri
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   486
                + (!subprotocol.isEmpty() ? ", subprotocol=" + subprotocol : "");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   487
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   488
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   489
    private MessageStreamConsumer messageConsumerOf(Listener listener) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   490
        // 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
   491
        // 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
   492
        // 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
   493
        // 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
   494
        return new MessageStreamConsumer() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   495
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   496
            @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   497
            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
   498
                receiver.acknowledge();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   499
                synchronized (WebSocketImpl.this.lock) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   500
                    try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   501
                        listener.onText(WebSocketImpl.this, data, part);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   502
                    } catch (Exception e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   503
                        signalError(e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   504
                    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   505
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   506
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   507
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   508
            @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   509
            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
   510
                receiver.acknowledge();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   511
                synchronized (WebSocketImpl.this.lock) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   512
                    try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   513
                        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
   514
                    } catch (Exception e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   515
                        signalError(e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   516
                    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   517
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   518
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   519
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   520
            @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   521
            public void onPing(ByteBuffer data) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   522
                receiver.acknowledge();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   523
                // 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
   524
                // 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
   525
                // 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
   526
                ByteBuffer slice = data.slice();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   527
                ByteBuffer copy = ByteBuffer.allocate(data.remaining())
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   528
                        .put(data)
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   529
                        .flip();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   530
                // Non-exclusive send;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   531
                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
   532
                pongSent.whenComplete(
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   533
                        (r, error) -> {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   534
                            if (error != null) {
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   535
                                WebSocketImpl.this.signalError(
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   536
                                        Utils.getCompletionCause(error));
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   537
                            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   538
                        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   539
                );
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   540
                synchronized (WebSocketImpl.this.lock) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   541
                    try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   542
                        listener.onPing(WebSocketImpl.this, slice);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   543
                    } catch (Exception e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   544
                        signalError(e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   545
                    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   546
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   547
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   548
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   549
            @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   550
            public void onPong(ByteBuffer data) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   551
                receiver.acknowledge();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   552
                synchronized (WebSocketImpl.this.lock) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   553
                    try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   554
                        listener.onPong(WebSocketImpl.this, data.slice());
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   555
                    } catch (Exception e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   556
                        signalError(e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   557
                    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   558
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   559
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   560
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   561
            @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   562
            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
   563
                receiver.acknowledge();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   564
                processClose(statusCode, reason.toString());
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
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   567
            @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   568
            public void onError(Exception error) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   569
                // 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
   570
                // 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
   571
                // 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
   572
                // 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
   573
                // notifying the Listener.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   574
                if (!(error instanceof FailWebSocketException)) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   575
                    signalError(error);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   576
                } else {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   577
                    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
   578
                    int code = ((FailWebSocketException) error).getStatusCode();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   579
                    enqueueClose(new Close(code, ""))
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   580
                            .whenComplete((r, e) -> {
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   581
                                if (e != null) {
55763
634d8e14c172 http-client-branch: intial load from jdk10/sandbox
chegar
parents: 47216
diff changeset
   582
                                    ex.addSuppressed(Utils.getCompletionCause(e));
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   583
                                }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   584
                                try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   585
                                    channel.close();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   586
                                } catch (IOException e1) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   587
                                    ex.addSuppressed(e1);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   588
                                } finally {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   589
                                    closed.set(true);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   590
                                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   591
                                signalError(ex);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   592
                            });
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   593
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   594
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   595
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   596
            @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   597
            public void onComplete() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   598
                processClose(CLOSED_ABNORMALLY, "");
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   599
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   600
        };
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   601
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   602
}