src/java.net.http/share/classes/jdk/internal/net/http/websocket/WebSocketImpl.java
author chegar
Wed, 02 May 2018 02:36:17 -0700
changeset 49944 4690a2871b44
parent 49765 ee6f7a61f3a5
child 50681 4254bed3c09d
child 56451 9585061fdb04
permissions -rw-r--r--
8202423: Small HTTP Client refresh Reviewed-by: chegar, dfuchs, michaelm, prappo Contributed-by: Chris Hegarty <chris.hegarty@oracle.com>, Daniel Fuchs <daniel.fuchs@oracle.com>, Michael McMahon <michael.x.mcmahon@oracle.com>, Pavel Rappo <pavel.rappo@oracle.com>
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
/*
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
     2
 * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
     4
 *
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
     7
 * published by the Free Software Foundation.  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
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    26
package jdk.internal.net.http.websocket;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    27
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    28
import jdk.internal.net.http.common.Demand;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    29
import jdk.internal.net.http.common.Log;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    30
import jdk.internal.net.http.common.Logger;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    31
import jdk.internal.net.http.common.MinimalFuture;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    32
import jdk.internal.net.http.common.SequentialScheduler;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    33
import jdk.internal.net.http.common.Utils;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    34
import jdk.internal.net.http.websocket.OpeningHandshake.Result;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    35
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    36
import java.io.IOException;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    37
import java.lang.System.Logger.Level;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    38
import java.lang.ref.Reference;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    39
import java.net.ProtocolException;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    40
import java.net.URI;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    41
import java.net.http.WebSocket;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    42
import java.nio.ByteBuffer;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    43
import java.nio.CharBuffer;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    44
import java.nio.charset.CharacterCodingException;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    45
import java.nio.charset.CharsetEncoder;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    46
import java.nio.charset.CodingErrorAction;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    47
import java.nio.charset.StandardCharsets;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    48
import java.util.Objects;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    49
import java.util.concurrent.CompletableFuture;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    50
import java.util.concurrent.CompletionStage;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    51
import java.util.concurrent.atomic.AtomicBoolean;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    52
import java.util.concurrent.atomic.AtomicLong;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    53
import java.util.concurrent.atomic.AtomicReference;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    54
import java.util.function.BiConsumer;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    55
import java.util.function.Function;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    56
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    57
import static java.util.Objects.requireNonNull;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    58
import static jdk.internal.net.http.common.MinimalFuture.failedFuture;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    59
import static jdk.internal.net.http.websocket.StatusCodes.CLOSED_ABNORMALLY;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    60
import static jdk.internal.net.http.websocket.StatusCodes.NO_STATUS_CODE;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    61
import static jdk.internal.net.http.websocket.StatusCodes.isLegalToSendFromClient;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    62
import static jdk.internal.net.http.websocket.WebSocketImpl.State.BINARY;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    63
import static jdk.internal.net.http.websocket.WebSocketImpl.State.CLOSE;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    64
import static jdk.internal.net.http.websocket.WebSocketImpl.State.ERROR;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    65
import static jdk.internal.net.http.websocket.WebSocketImpl.State.IDLE;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    66
import static jdk.internal.net.http.websocket.WebSocketImpl.State.OPEN;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    67
import static jdk.internal.net.http.websocket.WebSocketImpl.State.PING;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    68
import static jdk.internal.net.http.websocket.WebSocketImpl.State.PONG;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    69
import static jdk.internal.net.http.websocket.WebSocketImpl.State.TEXT;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    70
import static jdk.internal.net.http.websocket.WebSocketImpl.State.WAITING;
42460
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
/*
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    73
 * A WebSocket client.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    74
 */
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    75
public final class WebSocketImpl implements WebSocket {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    76
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    77
    private static final Logger debug =
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    78
            Utils.getWebSocketLogger("[WebSocket]"::toString, Utils.DEBUG_WS);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    79
    private final AtomicLong sendCounter = new AtomicLong();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    80
    private final AtomicLong receiveCounter = new AtomicLong();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    81
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    82
    enum State {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    83
        OPEN,
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    84
        IDLE,
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    85
        WAITING,
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    86
        TEXT,
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    87
        BINARY,
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    88
        PING,
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    89
        PONG,
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    90
        CLOSE,
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    91
        ERROR;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    92
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    93
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    94
    private final AtomicReference<ByteBuffer> lastAutomaticPong = new AtomicReference<>();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    95
    private final MinimalFuture<WebSocket> DONE = MinimalFuture.completedFuture(this);
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    96
    private volatile boolean inputClosed;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
    97
    private final AtomicBoolean outputClosed = new AtomicBoolean();
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    98
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    99
    private final AtomicReference<State> state = new AtomicReference<>(OPEN);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   100
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   101
    /* Components of calls to Listener's methods */
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   102
    private boolean last;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   103
    private ByteBuffer binaryData;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   104
    private CharSequence text;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   105
    private int statusCode;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   106
    private String reason;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   107
    private final AtomicReference<Throwable> error = new AtomicReference<>();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   108
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   109
    private final URI uri;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   110
    private final String subprotocol;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   111
    private final Listener listener;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   112
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   113
    private final AtomicBoolean pendingTextOrBinary = new AtomicBoolean();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   114
    private final AtomicBoolean pendingPingOrPong = new AtomicBoolean();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   115
    private final Transport transport;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   116
    private final SequentialScheduler receiveScheduler
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   117
            = new SequentialScheduler(new ReceiveTask());
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   118
    private final Demand demand = new Demand();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   119
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   120
    public static CompletableFuture<WebSocket> newInstanceAsync(BuilderImpl b) {
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   121
        Function<Result, WebSocket> newWebSocket = r -> {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   122
            WebSocket ws = newInstance(b.getUri(),
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   123
                                       r.subprotocol,
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   124
                                       b.getListener(),
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   125
                                       r.transport);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   126
            // Make sure we don't release the builder until this lambda
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   127
            // has been executed. The builder has a strong reference to
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   128
            // the HttpClientFacade, and we want to keep that live until
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   129
            // after the raw channel is created and passed to WebSocketImpl.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   130
            Reference.reachabilityFence(b);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   131
            return ws;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   132
        };
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   133
        OpeningHandshake h;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   134
        try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   135
            h = new OpeningHandshake(b);
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   136
        } catch (Throwable e) {
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   137
            return failedFuture(e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   138
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   139
        return h.send().thenApply(newWebSocket);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   140
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   141
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   142
    /* Exposed for testing purposes */
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   143
    static WebSocketImpl newInstance(URI uri,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   144
                                     String subprotocol,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   145
                                     Listener listener,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   146
                                     TransportFactory transport) {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   147
        WebSocketImpl ws = new WebSocketImpl(uri, subprotocol, listener, transport);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   148
        // This initialisation is outside of the constructor for the sake of
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   149
        // safe publication of WebSocketImpl.this
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   150
        ws.signalOpen();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   151
        return ws;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   152
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   153
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   154
    private WebSocketImpl(URI uri,
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   155
                          String subprotocol,
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   156
                          Listener listener,
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   157
                          TransportFactory transportFactory) {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   158
        this.uri = requireNonNull(uri);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   159
        this.subprotocol = requireNonNull(subprotocol);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   160
        this.listener = requireNonNull(listener);
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   161
        // Why 6? 1 sendPing/sendPong + 1 sendText/sendBinary + 1 Close +
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   162
        // 2 automatic Ping replies + 1 automatic Close = 6 messages
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   163
        // Why 2 automatic Pong replies? One is being sent, but the byte buffer
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   164
        // has been set to null, another just has been added.
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   165
        this.transport = transportFactory.createTransport(new MessageQueue(6),
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   166
                new SignallingMessageConsumer());
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   167
    }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   168
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   169
    // FIXME: add to action handling of errors -> signalError()
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   170
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   171
    @Override
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   172
    public CompletableFuture<WebSocket> sendText(CharSequence message,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   173
                                                 boolean last) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   174
        Objects.requireNonNull(message);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   175
        long id = 0;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   176
        if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   177
            id = sendCounter.incrementAndGet();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   178
            debug.log("enter send text %s payload length=%s last=%s",
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   179
                      id, message.length(), last);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   180
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   181
        CompletableFuture<WebSocket> result;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   182
        if (!setPendingTextOrBinary()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   183
            result = failedFuture(new IllegalStateException("Send pending"));
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   184
        } else {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   185
            result = transport.sendText(message, last, this,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   186
                                        (r, e) -> clearPendingTextOrBinary());
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   187
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   188
        if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   189
            debug.log("exit send text %s returned %s", id, result);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   190
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   191
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   192
        return replaceNull(result);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   193
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   194
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   195
    @Override
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   196
    public CompletableFuture<WebSocket> sendBinary(ByteBuffer message,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   197
                                                   boolean last) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   198
        Objects.requireNonNull(message);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   199
        long id = 0;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   200
        if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   201
            id = sendCounter.incrementAndGet();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   202
            debug.log("enter send binary %s payload=%s last=%s",
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   203
                      id, message, last);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   204
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   205
        CompletableFuture<WebSocket> result;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   206
        if (!setPendingTextOrBinary()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   207
            result = failedFuture(new IllegalStateException("Send pending"));
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   208
        } else {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   209
            result = transport.sendBinary(message, last, this,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   210
                                          (r, e) -> clearPendingTextOrBinary());
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   211
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   212
        if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   213
            debug.log("exit send binary %s returned %s", id, result);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   214
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   215
        return replaceNull(result);
42460
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
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   218
    private void clearPendingTextOrBinary() {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   219
        pendingTextOrBinary.set(false);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   220
    }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   221
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   222
    private boolean setPendingTextOrBinary() {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   223
        return pendingTextOrBinary.compareAndSet(false, true);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   224
    }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   225
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   226
    private CompletableFuture<WebSocket> replaceNull(
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   227
            CompletableFuture<WebSocket> cf)
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   228
    {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   229
        if (cf == null) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   230
            return DONE;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   231
        } else {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   232
            return cf;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   233
        }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   234
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   235
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   236
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   237
    public CompletableFuture<WebSocket> sendPing(ByteBuffer message) {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   238
        Objects.requireNonNull(message);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   239
        long id = 0;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   240
        if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   241
            id = sendCounter.incrementAndGet();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   242
            debug.log("enter send ping %s payload=%s", id, message);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   243
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   244
        CompletableFuture<WebSocket> result;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   245
        if (!setPendingPingOrPong()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   246
            result = failedFuture(new IllegalStateException("Send pending"));
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   247
        } else {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   248
            result = transport.sendPing(message, this,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   249
                                        (r, e) -> clearPendingPingOrPong());
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   250
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   251
        if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   252
            debug.log("exit send ping %s returned %s", id, result);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   253
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   254
        return replaceNull(result);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   255
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   256
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   257
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   258
    public CompletableFuture<WebSocket> sendPong(ByteBuffer message) {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   259
        Objects.requireNonNull(message);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   260
        long id = 0;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   261
        if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   262
            id = sendCounter.incrementAndGet();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   263
            debug.log("enter send pong %s payload=%s", id, message);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   264
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   265
        CompletableFuture<WebSocket> result;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   266
        if (!setPendingPingOrPong()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   267
            result = failedFuture(new IllegalStateException("Send pending"));
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   268
        } else {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   269
            result =  transport.sendPong(message, this,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   270
                                         (r, e) -> clearPendingPingOrPong());
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   271
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   272
        if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   273
            debug.log("exit send pong %s returned %s", id, result);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   274
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   275
        return replaceNull(result);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   276
    }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   277
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   278
    private boolean setPendingPingOrPong() {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   279
        return pendingPingOrPong.compareAndSet(false, true);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   280
    }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   281
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   282
    private void clearPendingPingOrPong() {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   283
        pendingPingOrPong.set(false);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   284
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   285
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   286
    @Override
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   287
    public CompletableFuture<WebSocket> sendClose(int statusCode,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   288
                                                  String reason) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   289
        Objects.requireNonNull(reason);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   290
        long id = 0;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   291
        if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   292
            id = sendCounter.incrementAndGet();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   293
            debug.log("enter send close %s statusCode=%s reason.length=%s",
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   294
                      id, statusCode, reason.length());
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   295
        }
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   296
        CompletableFuture<WebSocket> result;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   297
        // Close message is the only type of message whose validity is checked
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   298
        // in the corresponding send method. This is made in order to close the
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   299
        // output in place. Otherwise the number of Close messages in queue
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   300
        // would not be bounded.
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   301
        if (!isLegalToSendFromClient(statusCode)) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   302
            result = failedFuture(new IllegalArgumentException("statusCode"));
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   303
        } else if (!isLegalReason(reason)) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   304
            result = failedFuture(new IllegalArgumentException("reason"));
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   305
        } else if (!outputClosed.compareAndSet(false, true)){
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   306
            result = failedFuture(new IOException("Output closed"));
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   307
        } else {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   308
            result = sendClose0(statusCode, reason);
45119
decbbff9fdb4 8179021: Latest bugfixes to WebSocket/HPACK from the sandbox repo
prappo
parents: 43730
diff changeset
   309
        }
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   310
        if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   311
            debug.log("exit send close %s returned %s", id, result);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   312
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   313
        return replaceNull(result);
42460
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
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   316
    private static boolean isLegalReason(String reason) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   317
        if (reason.length() > 123) { // quick check
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   318
            return false;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   319
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   320
        CharsetEncoder encoder = StandardCharsets.UTF_8.newEncoder()
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   321
                        .onMalformedInput(CodingErrorAction.REPORT)
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   322
                        .onUnmappableCharacter(CodingErrorAction.REPORT);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   323
        ByteBuffer bytes;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   324
        try {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   325
            bytes = encoder.encode(CharBuffer.wrap(reason));
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   326
        } catch (CharacterCodingException ignored) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   327
            return false;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   328
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   329
        return bytes.remaining() <= 123;
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
    /*
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   333
     * The implementation uses this method internally to send Close messages
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   334
     * with codes that are not allowed to be sent through the API.
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   335
     */
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   336
    private CompletableFuture<WebSocket> sendClose0(int statusCode,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   337
                                                    String reason) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   338
        return transport.sendClose(statusCode, reason, this,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   339
                                   (r, e) -> processCloseError(e));
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   340
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   341
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   342
    private void processCloseError(Throwable e) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   343
        if (e == null) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   344
            debug.log("send close completed successfully");
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   345
        } else {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   346
            debug.log("send close completed with error", e);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   347
        }
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   348
        outputClosed.set(true);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   349
        try {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   350
            transport.closeOutput();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   351
        } catch (IOException ignored) { }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   352
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   353
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   354
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   355
    public void request(long n) {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   356
        if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   357
            debug.log("request %s", n);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   358
        }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   359
        if (demand.increase(n)) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   360
            receiveScheduler.runOrSchedule();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   361
        }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   362
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   363
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   364
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   365
    public String getSubprotocol() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   366
        return subprotocol;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   367
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   368
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   369
    @Override
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   370
    public boolean isOutputClosed() {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   371
        return outputClosed.get();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   372
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   373
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   374
    @Override
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   375
    public boolean isInputClosed() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   376
        return inputClosed;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   377
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   378
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   379
    @Override
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   380
    public void abort() {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   381
        if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   382
            debug.log("abort");
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   383
        }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   384
        inputClosed = true;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   385
        outputClosed.set(true);
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   386
        receiveScheduler.stop();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   387
        close();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   388
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   389
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   390
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   391
    public String toString() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   392
        return super.toString()
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   393
                + "[uri=" + uri
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   394
                + (!subprotocol.isEmpty() ? ", subprotocol=" + subprotocol : "")
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   395
                + "]";
42460
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
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   398
    /*
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   399
     * The assumptions about order is as follows:
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   400
     *
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   401
     *     - state is never changed more than twice inside the `run` method:
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   402
     *       x --(1)--> IDLE --(2)--> y (otherwise we're loosing events, or
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   403
     *       overwriting parts of messages creating a mess since there's no
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   404
     *       queueing)
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   405
     *     - OPEN is always the first state
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   406
     *     - no messages are requested/delivered before onOpen is called (this
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   407
     *       is implemented by making WebSocket instance accessible first in
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   408
     *       onOpen)
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   409
     *     - after the state has been observed as CLOSE/ERROR, the scheduler
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   410
     *       is stopped
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   411
     */
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   412
    private class ReceiveTask extends SequentialScheduler.CompleteRestartableTask {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   413
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   414
        // Transport only asked here and nowhere else because we must make sure
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   415
        // onOpen is invoked first and no messages become pending before onOpen
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   416
        // finishes
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   417
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   418
        @Override
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   419
        public void run() {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   420
            if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   421
                debug.log("enter receive task");
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   422
            }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   423
            loop:
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   424
            while (!receiveScheduler.isStopped()) {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   425
                State s = state.get();
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   426
                if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   427
                    debug.log("receive state: %s", s);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   428
                }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   429
                try {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   430
                    switch (s) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   431
                        case OPEN:
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   432
                            processOpen();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   433
                            tryChangeState(OPEN, IDLE);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   434
                            break;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   435
                        case TEXT:
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   436
                            processText();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   437
                            tryChangeState(TEXT, IDLE);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   438
                            break;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   439
                        case BINARY:
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   440
                            processBinary();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   441
                            tryChangeState(BINARY, IDLE);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   442
                            break;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   443
                        case PING:
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   444
                            processPing();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   445
                            tryChangeState(PING, IDLE);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   446
                            break;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   447
                        case PONG:
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   448
                            processPong();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   449
                            tryChangeState(PONG, IDLE);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   450
                            break;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   451
                        case CLOSE:
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   452
                            processClose();
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   453
                            break loop;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   454
                        case ERROR:
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   455
                            processError();
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   456
                            break loop;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   457
                        case IDLE:
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   458
                            if (demand.tryDecrement()
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   459
                                    && tryChangeState(IDLE, WAITING)) {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   460
                                transport.request(1);
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   461
                            }
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   462
                            break loop;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   463
                        case WAITING:
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   464
                            // For debugging spurious signalling: when there was
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   465
                            // a signal, but apparently nothing has changed
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   466
                            break loop;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   467
                        default:
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   468
                            throw new InternalError(String.valueOf(s));
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   469
                    }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   470
                } catch (Throwable t) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   471
                    signalError(t);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   472
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   473
            }
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   474
            if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   475
                debug.log("exit receive task");
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   476
            }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   477
        }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   478
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   479
        private void processError() throws IOException {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   480
            if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   481
                debug.log("processError");
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   482
            }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   483
            transport.closeInput();
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   484
            receiveScheduler.stop();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   485
            Throwable err = error.get();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   486
            if (err instanceof FailWebSocketException) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   487
                int code1 = ((FailWebSocketException) err).getStatusCode();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   488
                err = new ProtocolException().initCause(err);
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   489
                if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   490
                    debug.log("failing %s with error=%s statusCode=%s",
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   491
                              WebSocketImpl.this, err, code1);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   492
                }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   493
                sendCloseSilently(code1);
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   494
            }
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   495
            long id = 0;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   496
            if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   497
                id = receiveCounter.incrementAndGet();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   498
                debug.log("enter onError %s error=%s", id, err);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   499
            }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   500
            try {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   501
                listener.onError(WebSocketImpl.this, err);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   502
            } finally {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   503
                if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   504
                    debug.log("exit onError %s", id);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   505
                }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   506
            }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   507
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   508
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   509
        private void processClose() throws IOException {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   510
            debug.log("processClose");
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   511
            transport.closeInput();
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   512
            receiveScheduler.stop();
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   513
            CompletionStage<?> cs = null; // when the listener is ready to close
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   514
            long id = 0;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   515
            if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   516
                id = receiveCounter.incrementAndGet();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   517
                debug.log("enter onClose %s statusCode=%s reason.length=%s",
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   518
                          id, statusCode, reason.length());
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   519
            }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   520
            try {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   521
                cs = listener.onClose(WebSocketImpl.this, statusCode, reason);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   522
            } finally {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   523
                debug.log("exit onClose %s returned %s", id, cs);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   524
            }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   525
            if (cs == null) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   526
                cs = DONE;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   527
            }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   528
            int code;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   529
            if (statusCode == NO_STATUS_CODE || statusCode == CLOSED_ABNORMALLY) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   530
                code = NORMAL_CLOSURE;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   531
                debug.log("using statusCode %s instead of %s",
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   532
                          statusCode, code);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   533
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   534
            } else {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   535
                code = statusCode;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   536
            }
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   537
            cs.whenComplete((r, e) -> {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   538
                if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   539
                    debug.log("CompletionStage returned by onClose completed result=%s error=%s",
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   540
                              r, e);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   541
                }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   542
                sendCloseSilently(code);
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   543
            });
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   544
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   545
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   546
        private void processPong() {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   547
            long id = 0;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   548
            if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   549
                id = receiveCounter.incrementAndGet();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   550
                debug.log("enter onPong %s payload=%s",
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   551
                          id, binaryData);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   552
            }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   553
            CompletionStage<?> cs = null;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   554
            try {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   555
                cs = listener.onPong(WebSocketImpl.this, binaryData);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   556
            } finally {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   557
                if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   558
                    debug.log("exit onPong %s returned %s", id, cs);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   559
                }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   560
            }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   561
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   562
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   563
        private void processPing() {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   564
            if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   565
                debug.log("processPing");
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   566
            }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   567
            // A full copy of this (small) data is made. This way sending a
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   568
            // replying Pong could be done in parallel with the listener
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   569
            // handling this Ping.
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   570
            ByteBuffer slice = binaryData.slice();
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   571
            if (!outputClosed.get()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   572
                ByteBuffer copy = ByteBuffer.allocate(binaryData.remaining())
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   573
                        .put(binaryData)
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   574
                        .flip();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   575
                if (!trySwapAutomaticPong(copy)) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   576
                    // Non-exclusive send;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   577
                    BiConsumer<WebSocketImpl, Throwable> reporter = (r, e) -> {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   578
                        if (e != null) { // TODO: better error handing. What if already closed?
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   579
                            signalError(Utils.getCompletionCause(e));
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   580
                        }
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   581
                    };
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   582
                    transport.sendPong(WebSocketImpl.this::clearAutomaticPong,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   583
                                       WebSocketImpl.this,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   584
                                       reporter);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   585
                }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   586
            }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   587
            long id = 0;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   588
            if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   589
                id = receiveCounter.incrementAndGet();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   590
                debug.log("enter onPing %s payload=%s", id, slice);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   591
            }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   592
            CompletionStage<?> cs = null;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   593
            try {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   594
                cs = listener.onPing(WebSocketImpl.this, slice);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   595
            } finally {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   596
                if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   597
                    debug.log("exit onPing %s returned %s", id, cs);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   598
                }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   599
            }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   600
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   601
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   602
        private void processBinary() {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   603
            long id = 0;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   604
            if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   605
                id = receiveCounter.incrementAndGet();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   606
                debug.log("enter onBinary %s payload=%s last=%s",
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   607
                          id, binaryData, last);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   608
            }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   609
            CompletionStage<?> cs = null;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   610
            try {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   611
                cs = listener.onBinary(WebSocketImpl.this, binaryData, last);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   612
            } finally {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   613
                if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   614
                    debug.log("exit onBinary %s returned %s", id, cs);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   615
                }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   616
            }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   617
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   618
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   619
        private void processText() {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   620
            long id = 0;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   621
            if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   622
                id = receiveCounter.incrementAndGet();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   623
                debug.log("enter onText %s payload.length=%s last=%s",
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   624
                          id, text.length(), last);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   625
            }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   626
            CompletionStage<?> cs = null;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   627
            try {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   628
                cs = listener.onText(WebSocketImpl.this, text, last);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   629
            } finally {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   630
                if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   631
                    debug.log("exit onText %s returned %s", id, cs);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   632
                }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   633
            }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   634
        }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   635
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   636
        private void processOpen() {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   637
            long id = 0;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   638
            if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   639
                id = receiveCounter.incrementAndGet();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   640
                debug.log("enter onOpen %s", id);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   641
            }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   642
            try {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   643
                listener.onOpen(WebSocketImpl.this);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   644
            } finally {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   645
                if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   646
                    debug.log("exit onOpen %s", id);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   647
                }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   648
            }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   649
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   650
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   651
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   652
    private void sendCloseSilently(int statusCode) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   653
        sendClose0(statusCode, "").whenComplete((r, e) -> {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   654
            if (e != null) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   655
                if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   656
                    debug.log("automatic closure completed with error",
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   657
                              (Object) e);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   658
                }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   659
            }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   660
        });
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   661
    }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   662
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   663
    private ByteBuffer clearAutomaticPong() {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   664
        ByteBuffer data;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   665
        do {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   666
            data = lastAutomaticPong.get();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   667
            if (data == null) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   668
                // This method must never be called unless a message that is
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   669
                // using it has been added previously
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   670
                throw new InternalError();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   671
            }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   672
        } while (!lastAutomaticPong.compareAndSet(data, null));
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   673
        return data;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   674
    }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   675
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   676
    // bound pings
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   677
    private boolean trySwapAutomaticPong(ByteBuffer copy) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   678
        ByteBuffer message;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   679
        boolean swapped;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   680
        while (true) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   681
            message = lastAutomaticPong.get();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   682
            if (message == null) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   683
                if (!lastAutomaticPong.compareAndSet(null, copy)) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   684
                    // It's only this method that can change null to ByteBuffer,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   685
                    // and this method is invoked at most by one thread at a
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   686
                    // time. Thus no failure in the atomic operation above is
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   687
                    // expected.
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   688
                    throw new InternalError();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   689
                }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   690
                swapped = false;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   691
                break;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   692
            } else if (lastAutomaticPong.compareAndSet(message, copy)) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   693
                swapped = true;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   694
                break;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   695
            }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   696
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   697
        if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   698
            debug.log("swapped automatic pong from %s to %s",
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   699
                      message, copy);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   700
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   701
        return swapped;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   702
    }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   703
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   704
    private void signalOpen() {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   705
        debug.log("signalOpen");
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   706
        receiveScheduler.runOrSchedule();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   707
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   708
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   709
    private void signalError(Throwable error) {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   710
        if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   711
            debug.log("signalError %s", (Object) error);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   712
        }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   713
        inputClosed = true;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   714
        outputClosed.set(true);
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   715
        if (!this.error.compareAndSet(null, error) || !trySetState(ERROR)) {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   716
            if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   717
                debug.log("signalError", error);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   718
            }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   719
            Log.logError(error);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   720
        } else {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   721
            close();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   722
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   723
    }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   724
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   725
    private void close() {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   726
        if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   727
            debug.log("close");
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   728
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   729
        Throwable first = null;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   730
        try {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   731
            transport.closeInput();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   732
        } catch (Throwable t1) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   733
            first = t1;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   734
        } finally {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   735
            Throwable second = null;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   736
            try {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   737
                transport.closeOutput();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   738
            } catch (Throwable t2) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   739
                second = t2;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   740
            } finally {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   741
                Throwable e = null;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   742
                if (first != null && second != null) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   743
                    first.addSuppressed(second);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   744
                    e = first;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   745
                } else if (first != null) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   746
                    e = first;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   747
                } else if (second != null) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   748
                    e = second;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   749
                }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   750
                if (e != null) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   751
                    if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   752
                        debug.log("exception in close", e);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   753
                    }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   754
                }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   755
            }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   756
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   757
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   758
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   759
    private void signalClose(int statusCode, String reason) {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   760
        // FIXME: make sure no race reason & close are not intermixed
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   761
        inputClosed = true;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   762
        this.statusCode = statusCode;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   763
        this.reason = reason;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   764
        boolean managed = trySetState(CLOSE);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   765
        if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   766
            debug.log("signalClose statusCode=%s reason.length=%s: %s",
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   767
                      statusCode, reason.length(), managed);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   768
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   769
        if (managed) {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   770
            try {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   771
                transport.closeInput();
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   772
            } catch (Throwable t) {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   773
                if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   774
                    debug.log("exception closing input", (Object) t);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   775
                }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   776
            }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   777
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   778
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   779
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   780
    private class SignallingMessageConsumer implements MessageStreamConsumer {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   781
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   782
        @Override
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   783
        public void onText(CharSequence data, boolean last) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   784
            transport.acknowledgeReception();
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   785
            text = data;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   786
            WebSocketImpl.this.last = last;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   787
            tryChangeState(WAITING, TEXT);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   788
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   789
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   790
        @Override
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   791
        public void onBinary(ByteBuffer data, boolean last) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   792
            transport.acknowledgeReception();
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   793
            binaryData = data;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   794
            WebSocketImpl.this.last = last;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   795
            tryChangeState(WAITING, BINARY);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   796
        }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   797
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   798
        @Override
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   799
        public void onPing(ByteBuffer data) {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   800
            transport.acknowledgeReception();
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   801
            binaryData = data;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   802
            tryChangeState(WAITING, PING);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   803
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   804
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   805
        @Override
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   806
        public void onPong(ByteBuffer data) {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   807
            transport.acknowledgeReception();
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   808
            binaryData = data;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   809
            tryChangeState(WAITING, PONG);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   810
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   811
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   812
        @Override
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   813
        public void onClose(int statusCode, CharSequence reason) {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   814
            transport.acknowledgeReception();
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   815
            signalClose(statusCode, reason.toString());
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   816
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   817
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   818
        @Override
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   819
        public void onComplete() {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   820
            transport.acknowledgeReception();
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   821
            signalClose(CLOSED_ABNORMALLY, "");
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   822
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   823
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   824
        @Override
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   825
        public void onError(Throwable error) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   826
            signalError(error);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   827
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   828
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   829
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   830
    private boolean trySetState(State newState) {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   831
        State currentState;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   832
        boolean success = false;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   833
        while (true) {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   834
            currentState = state.get();
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   835
            if (currentState == ERROR || currentState == CLOSE) {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   836
                break;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   837
            } else if (state.compareAndSet(currentState, newState)) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   838
                receiveScheduler.runOrSchedule();
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   839
                success = true;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   840
                break;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   841
            }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   842
        }
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   843
        if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   844
            debug.log("set state %s (previous %s) %s",
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   845
                      newState, currentState, success);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   846
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   847
        return success;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   848
    }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   849
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   850
    private boolean tryChangeState(State expectedState, State newState) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   851
        State witness = state.compareAndExchange(expectedState, newState);
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   852
        boolean success = false;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   853
        if (witness == expectedState) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   854
            receiveScheduler.runOrSchedule();
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   855
            success = true;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   856
        } else if (witness != ERROR && witness != CLOSE) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   857
            // This should be the only reason for inability to change the state
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   858
            // from IDLE to WAITING: the state has changed to terminal
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   859
            throw new InternalError();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   860
        }
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   861
        if (debug.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   862
            debug.log("change state from %s to %s %s",
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   863
                      expectedState, newState, success);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   864
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   865
        return success;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   866
    }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   867
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   868
    /* Exposed for testing purposes */
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   869
    protected Transport transport() {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48083
diff changeset
   870
        return transport;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   871
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   872
}