jdk/src/java.httpclient/share/classes/java/net/http/WSFrameConsumer.java
author prappo
Mon, 09 May 2016 23:33:09 +0100
changeset 37874 02589df0999a
child 38856 cc3a0d1e96e0
permissions -rw-r--r--
8087113: Websocket API and implementation Reviewed-by: chegar
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
37874
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
     1
/*
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
     2
 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
     4
 *
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    10
 *
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    15
 * accompanied this code).
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    16
 *
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    20
 *
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    23
 * questions.
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    24
 */
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    25
package java.net.http;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    26
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    27
import java.net.http.WSFrame.Opcode;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    28
import java.net.http.WebSocket.MessagePart;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    29
import java.nio.ByteBuffer;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    30
import java.nio.CharBuffer;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    31
import java.nio.charset.CharacterCodingException;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    32
import java.util.concurrent.atomic.AtomicInteger;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    33
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    34
import static java.lang.String.format;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    35
import static java.lang.System.Logger.Level.TRACE;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    36
import static java.net.http.WSUtils.dump;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    37
import static java.net.http.WSUtils.logger;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    38
import static java.net.http.WebSocket.CloseCode.NOT_CONSISTENT;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    39
import static java.net.http.WebSocket.CloseCode.of;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    40
import static java.util.Objects.requireNonNull;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    41
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    42
/*
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    43
 * Consumes frame parts and notifies a message consumer, when there is
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    44
 * sufficient data to produce a message, or part thereof.
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    45
 *
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    46
 * Data consumed but not yet translated is accumulated until it's sufficient to
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    47
 * form a message.
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    48
 */
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    49
final class WSFrameConsumer implements WSFrame.Consumer {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    50
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    51
    private final AtomicInteger invocationOrder = new AtomicInteger();
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    52
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    53
    private final WSMessageConsumer output;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    54
    private final WSCharsetToolkit.Decoder decoder = new WSCharsetToolkit.Decoder();
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    55
    private boolean fin;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    56
    private Opcode opcode, originatingOpcode;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    57
    private MessagePart part = MessagePart.WHOLE;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    58
    private long payloadLen;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    59
    private WSShared<ByteBuffer> binaryData;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    60
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    61
    WSFrameConsumer(WSMessageConsumer output) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    62
        this.output = requireNonNull(output);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    63
    }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    64
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    65
    @Override
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    66
    public void fin(boolean value) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    67
        assert invocationOrder.compareAndSet(0, 1) : dump(invocationOrder, value);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    68
        if (logger.isLoggable(TRACE)) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    69
            // Checked for being loggable because of autoboxing of 'value'
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    70
            logger.log(TRACE, "Reading fin: {0}", value);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    71
        }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    72
        fin = value;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    73
    }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    74
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    75
    @Override
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    76
    public void rsv1(boolean value) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    77
        assert invocationOrder.compareAndSet(1, 2) : dump(invocationOrder, value);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    78
        if (logger.isLoggable(TRACE)) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    79
            logger.log(TRACE, "Reading rsv1: {0}", value);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    80
        }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    81
        if (value) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    82
            throw new WSProtocolException("5.2.", "rsv1 bit is set unexpectedly");
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    83
        }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    84
    }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    85
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    86
    @Override
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    87
    public void rsv2(boolean value) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    88
        assert invocationOrder.compareAndSet(2, 3) : dump(invocationOrder, value);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    89
        if (logger.isLoggable(TRACE)) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    90
            logger.log(TRACE, "Reading rsv2: {0}", value);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    91
        }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    92
        if (value) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    93
            throw new WSProtocolException("5.2.", "rsv2 bit is set unexpectedly");
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    94
        }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    95
    }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    96
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    97
    @Override
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    98
    public void rsv3(boolean value) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
    99
        assert invocationOrder.compareAndSet(3, 4) : dump(invocationOrder, value);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   100
        if (logger.isLoggable(TRACE)) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   101
            logger.log(TRACE, "Reading rsv3: {0}", value);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   102
        }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   103
        if (value) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   104
            throw new WSProtocolException("5.2.", "rsv3 bit is set unexpectedly");
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   105
        }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   106
    }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   107
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   108
    @Override
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   109
    public void opcode(Opcode v) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   110
        assert invocationOrder.compareAndSet(4, 5) : dump(invocationOrder, v);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   111
        logger.log(TRACE, "Reading opcode: {0}", v);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   112
        if (v == Opcode.PING || v == Opcode.PONG || v == Opcode.CLOSE) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   113
            if (!fin) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   114
                throw new WSProtocolException("5.5.", "A fragmented control frame " + v);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   115
            }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   116
            opcode = v;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   117
        } else if (v == Opcode.TEXT || v == Opcode.BINARY) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   118
            if (originatingOpcode != null) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   119
                throw new WSProtocolException
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   120
                        ("5.4.", format("An unexpected frame %s (fin=%s)", v, fin));
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   121
            }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   122
            opcode = v;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   123
            if (!fin) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   124
                originatingOpcode = v;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   125
            }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   126
        } else if (v == Opcode.CONTINUATION) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   127
            if (originatingOpcode == null) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   128
                throw new WSProtocolException
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   129
                        ("5.4.", format("An unexpected frame %s (fin=%s)", v, fin));
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   130
            }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   131
            opcode = v;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   132
        } else {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   133
            throw new WSProtocolException("5.2.", "An unknown opcode " + v);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   134
        }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   135
    }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   136
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   137
    @Override
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   138
    public void mask(boolean value) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   139
        assert invocationOrder.compareAndSet(5, 6) : dump(invocationOrder, value);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   140
        if (logger.isLoggable(TRACE)) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   141
            logger.log(TRACE, "Reading mask: {0}", value);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   142
        }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   143
        if (value) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   144
            throw new WSProtocolException
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   145
                    ("5.1.", "Received a masked frame from the server");
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   146
        }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   147
    }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   148
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   149
    @Override
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   150
    public void payloadLen(long value) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   151
        assert invocationOrder.compareAndSet(6, 7) : dump(invocationOrder, value);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   152
        if (logger.isLoggable(TRACE)) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   153
            logger.log(TRACE, "Reading payloadLen: {0}", value);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   154
        }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   155
        if (opcode.isControl()) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   156
            if (value > 125) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   157
                throw new WSProtocolException
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   158
                        ("5.5.", format("A control frame %s has a payload length of %s",
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   159
                                opcode, value));
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   160
            }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   161
            assert Opcode.CLOSE.isControl();
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   162
            if (opcode == Opcode.CLOSE && value == 1) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   163
                throw new WSProtocolException
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   164
                        ("5.5.1.", "A Close frame's status code is only 1 byte long");
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   165
            }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   166
        }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   167
        payloadLen = value;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   168
    }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   169
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   170
    @Override
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   171
    public void maskingKey(int value) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   172
        assert false : dump(invocationOrder, value);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   173
    }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   174
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   175
    @Override
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   176
    public void payloadData(WSShared<ByteBuffer> data, boolean isLast) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   177
        assert invocationOrder.compareAndSet(7, isLast ? 8 : 7)
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   178
                : dump(invocationOrder, data, isLast);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   179
        if (logger.isLoggable(TRACE)) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   180
            logger.log(TRACE, "Reading payloadData: data={0}, isLast={1}", data, isLast);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   181
        }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   182
        if (opcode.isControl()) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   183
            if (binaryData != null) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   184
                binaryData.put(data);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   185
                data.dispose();
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   186
            } else if (!isLast) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   187
                // The first chunk of the message
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   188
                int remaining = data.remaining();
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   189
                // It shouldn't be 125, otherwise the next chunk will be of size
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   190
                // 0, which is not what Reader promises to deliver (eager
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   191
                // reading)
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   192
                assert remaining < 125 : dump(remaining);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   193
                WSShared<ByteBuffer> b = WSShared.wrap(ByteBuffer.allocate(125)).put(data);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   194
                data.dispose();
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   195
                binaryData = b; // Will be disposed by the user
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   196
            } else {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   197
                // The only chunk; will be disposed by the user
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   198
                binaryData = data.position(data.limit()); // FIXME: remove this hack
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   199
            }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   200
        } else {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   201
            part = determinePart(isLast);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   202
            boolean text = opcode == Opcode.TEXT || originatingOpcode == Opcode.TEXT;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   203
            if (!text) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   204
                output.onBinary(part, data);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   205
            } else {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   206
                boolean binaryNonEmpty = data.hasRemaining();
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   207
                WSShared<CharBuffer> textData;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   208
                try {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   209
                    textData = decoder.decode(data, part.isLast());
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   210
                } catch (CharacterCodingException e) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   211
                    throw new WSProtocolException
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   212
                            ("5.6.", "Invalid UTF-8 sequence in frame " + opcode, NOT_CONSISTENT, e);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   213
                }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   214
                if (!(binaryNonEmpty && !textData.hasRemaining())) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   215
                    // If there's a binary data, that result in no text, then we
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   216
                    // don't deliver anything
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   217
                    output.onText(part, new WSDisposableText(textData));
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   218
                }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   219
            }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   220
        }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   221
    }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   222
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   223
    @Override
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   224
    public void endFrame() {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   225
        assert invocationOrder.compareAndSet(8, 0) : dump(invocationOrder);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   226
        if (opcode.isControl()) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   227
            binaryData.flip();
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   228
        }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   229
        switch (opcode) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   230
            case CLOSE:
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   231
                WebSocket.CloseCode cc;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   232
                String reason;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   233
                if (payloadLen == 0) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   234
                    cc = null;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   235
                    reason = "";
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   236
                } else {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   237
                    ByteBuffer b = binaryData.buffer();
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   238
                    int len = b.remaining();
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   239
                    assert 2 <= len && len <= 125 : dump(len, payloadLen);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   240
                    try {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   241
                        cc = of(b.getChar());
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   242
                        reason = WSCharsetToolkit.decode(b).toString();
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   243
                    } catch (IllegalArgumentException e) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   244
                        throw new WSProtocolException
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   245
                                ("5.5.1", "Incorrect status code", e);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   246
                    } catch (CharacterCodingException e) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   247
                        throw new WSProtocolException
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   248
                                ("5.5.1", "Close reason is a malformed UTF-8 sequence", e);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   249
                    }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   250
                }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   251
                binaryData.dispose(); // Manual dispose
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   252
                output.onClose(cc, reason);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   253
                break;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   254
            case PING:
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   255
                output.onPing(binaryData);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   256
                binaryData = null;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   257
                break;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   258
            case PONG:
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   259
                output.onPong(binaryData);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   260
                binaryData = null;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   261
                break;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   262
            default:
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   263
                assert opcode == Opcode.TEXT || opcode == Opcode.BINARY
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   264
                        || opcode == Opcode.CONTINUATION : dump(opcode);
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   265
                if (fin) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   266
                    // It is always the last chunk:
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   267
                    // either TEXT(FIN=TRUE)/BINARY(FIN=TRUE) or CONT(FIN=TRUE)
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   268
                    originatingOpcode = null;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   269
                }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   270
                break;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   271
        }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   272
        payloadLen = 0;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   273
        opcode = null;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   274
    }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   275
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   276
    private MessagePart determinePart(boolean isLast) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   277
        boolean lastChunk = fin && isLast;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   278
        switch (part) {
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   279
            case LAST:
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   280
            case WHOLE:
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   281
                return lastChunk ? MessagePart.WHOLE : MessagePart.FIRST;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   282
            case FIRST:
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   283
            case PART:
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   284
                return lastChunk ? MessagePart.LAST : MessagePart.PART;
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   285
            default:
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   286
                throw new InternalError(String.valueOf(part));
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   287
        }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   288
    }
02589df0999a 8087113: Websocket API and implementation
prappo
parents:
diff changeset
   289
}