src/java.net.http/share/classes/jdk/internal/net/http/websocket/MessageDecoder.java
branchhttp-client-branch
changeset 56304 065641767a75
parent 56295 898dfb226bd0
child 56320 f82729ca8660
equal deleted inserted replaced
56303:a82058c084ef 56304:065641767a75
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package jdk.internal.net.http.websocket;
    26 package jdk.internal.net.http.websocket;
    27 
    27 
       
    28 import jdk.internal.net.http.common.Utils;
    28 import jdk.internal.net.http.websocket.Frame.Opcode;
    29 import jdk.internal.net.http.websocket.Frame.Opcode;
    29 
    30 
    30 import java.net.http.WebSocket.MessagePart;
    31 import java.net.http.WebSocket.MessagePart;
    31 import java.nio.ByteBuffer;
    32 import java.nio.ByteBuffer;
    32 import java.nio.CharBuffer;
    33 import java.nio.CharBuffer;
    33 import java.nio.charset.CharacterCodingException;
    34 import java.nio.charset.CharacterCodingException;
    34 
    35 
    35 import static java.lang.String.format;
    36 import static java.lang.String.format;
       
    37 import java.lang.System.Logger.Level;
    36 import static java.nio.charset.StandardCharsets.UTF_8;
    38 import static java.nio.charset.StandardCharsets.UTF_8;
    37 import static java.util.Objects.requireNonNull;
    39 import static java.util.Objects.requireNonNull;
    38 import static jdk.internal.net.http.common.Utils.dump;
    40 import static jdk.internal.net.http.common.Utils.dump;
    39 import static jdk.internal.net.http.websocket.StatusCodes.NO_STATUS_CODE;
    41 import static jdk.internal.net.http.websocket.StatusCodes.NO_STATUS_CODE;
    40 import static jdk.internal.net.http.websocket.StatusCodes.isLegalToReceiveFromServer;
    42 import static jdk.internal.net.http.websocket.StatusCodes.isLegalToReceiveFromServer;
    47  * form a message.
    49  * form a message.
    48  */
    50  */
    49 /* Exposed for testing purposes */
    51 /* Exposed for testing purposes */
    50 class MessageDecoder implements Frame.Consumer {
    52 class MessageDecoder implements Frame.Consumer {
    51 
    53 
    52     private final static boolean DEBUG = false;
    54     private static final boolean DEBUG = Utils.DEBUG_WS;
       
    55     private static final System.Logger debug =
       
    56             Utils.getWebSocketLogger("[Input]"::toString, DEBUG);
       
    57 
    53     private final MessageStreamConsumer output;
    58     private final MessageStreamConsumer output;
    54     private final UTF8AccumulatingDecoder decoder = new UTF8AccumulatingDecoder();
    59     private final UTF8AccumulatingDecoder decoder = new UTF8AccumulatingDecoder();
    55     private boolean fin;
    60     private boolean fin;
    56     private Opcode opcode, originatingOpcode;
    61     private Opcode opcode, originatingOpcode;
    57     private MessagePart part = MessagePart.WHOLE;
    62     private MessagePart part = MessagePart.WHOLE;
    68         return output;
    73         return output;
    69     }
    74     }
    70 
    75 
    71     @Override
    76     @Override
    72     public void fin(boolean value) {
    77     public void fin(boolean value) {
    73         if (DEBUG) {
    78         debug.log(Level.DEBUG, "fin %s", value);
    74             System.out.printf("[Input] fin %s%n", value);
       
    75         }
       
    76         fin = value;
    79         fin = value;
    77     }
    80     }
    78 
    81 
    79     @Override
    82     @Override
    80     public void rsv1(boolean value) {
    83     public void rsv1(boolean value) {
    81         if (DEBUG) {
    84         debug.log(Level.DEBUG, "rsv1 %s", value);
    82             System.out.printf("[Input] rsv1 %s%n", value);
       
    83         }
       
    84         if (value) {
    85         if (value) {
    85             throw new FailWebSocketException("Unexpected rsv1 bit");
    86             throw new FailWebSocketException("Unexpected rsv1 bit");
    86         }
    87         }
    87     }
    88     }
    88 
    89 
    89     @Override
    90     @Override
    90     public void rsv2(boolean value) {
    91     public void rsv2(boolean value) {
    91         if (DEBUG) {
    92         debug.log(Level.DEBUG, "rsv2 %s", value);
    92             System.out.printf("[Input] rsv2 %s%n", value);
       
    93         }
       
    94         if (value) {
    93         if (value) {
    95             throw new FailWebSocketException("Unexpected rsv2 bit");
    94             throw new FailWebSocketException("Unexpected rsv2 bit");
    96         }
    95         }
    97     }
    96     }
    98 
    97 
    99     @Override
    98     @Override
   100     public void rsv3(boolean value) {
    99     public void rsv3(boolean value) {
   101         if (DEBUG) {
   100         debug.log(Level.DEBUG, "rsv3 %s", value);
   102             System.out.printf("[Input] rsv3 %s%n", value);
       
   103         }
       
   104         if (value) {
   101         if (value) {
   105             throw new FailWebSocketException("Unexpected rsv3 bit");
   102             throw new FailWebSocketException("Unexpected rsv3 bit");
   106         }
   103         }
   107     }
   104     }
   108 
   105 
   109     @Override
   106     @Override
   110     public void opcode(Opcode v) {
   107     public void opcode(Opcode v) {
   111         if (DEBUG) {
   108         debug.log(Level.DEBUG, "opcode %s", v);
   112             System.out.printf("[Input] opcode %s%n", v);
       
   113         }
       
   114         if (v == Opcode.PING || v == Opcode.PONG || v == Opcode.CLOSE) {
   109         if (v == Opcode.PING || v == Opcode.PONG || v == Opcode.CLOSE) {
   115             if (!fin) {
   110             if (!fin) {
   116                 throw new FailWebSocketException("Fragmented control frame  " + v);
   111                 throw new FailWebSocketException("Fragmented control frame  " + v);
   117             }
   112             }
   118             opcode = v;
   113             opcode = v;
   136         }
   131         }
   137     }
   132     }
   138 
   133 
   139     @Override
   134     @Override
   140     public void mask(boolean value) {
   135     public void mask(boolean value) {
   141         if (DEBUG) {
   136         debug.log(Level.DEBUG, "mask %s", value);
   142             System.out.printf("[Input] mask %s%n", value);
       
   143         }
       
   144         if (value) {
   137         if (value) {
   145             throw new FailWebSocketException("Masked frame received");
   138             throw new FailWebSocketException("Masked frame received");
   146         }
   139         }
   147     }
   140     }
   148 
   141 
   149     @Override
   142     @Override
   150     public void payloadLen(long value) {
   143     public void payloadLen(long value) {
   151         if (DEBUG) {
   144         debug.log(Level.DEBUG, "payloadLen %s", value);
   152             System.out.printf("[Input] payloadLen %s%n", value);
       
   153         }
       
   154         if (opcode.isControl()) {
   145         if (opcode.isControl()) {
   155             if (value > Frame.MAX_CONTROL_FRAME_PAYLOAD_LENGTH) {
   146             if (value > Frame.MAX_CONTROL_FRAME_PAYLOAD_LENGTH) {
   156                 throw new FailWebSocketException(
   147                 throw new FailWebSocketException(
   157                         format("%s's payload length %s", opcode, value));
   148                         format("%s's payload length %s", opcode, value));
   158             }
   149             }
   176         throw new InternalError();
   167         throw new InternalError();
   177     }
   168     }
   178 
   169 
   179     @Override
   170     @Override
   180     public void payloadData(ByteBuffer data) {
   171     public void payloadData(ByteBuffer data) {
   181         if (DEBUG) {
   172         debug.log(Level.DEBUG, "payload %s", data);
   182             System.out.printf("[Input] payload %s%n", data);
       
   183         }
       
   184         unconsumedPayloadLen -= data.remaining();
   173         unconsumedPayloadLen -= data.remaining();
   185         boolean isLast = unconsumedPayloadLen == 0;
   174         boolean isLast = unconsumedPayloadLen == 0;
   186         if (opcode.isControl()) {
   175         if (opcode.isControl()) {
   187             if (binaryData != null) { // An intermediate or the last chunk
   176             if (binaryData != null) { // An intermediate or the last chunk
   188                 binaryData.put(data);
   177                 binaryData.put(data);
   225         }
   214         }
   226     }
   215     }
   227 
   216 
   228     @Override
   217     @Override
   229     public void endFrame() {
   218     public void endFrame() {
   230         if (DEBUG) {
   219         debug.log(Level.DEBUG, "end frame");
   231             System.out.println("[Input] end frame");
       
   232         }
       
   233         if (opcode.isControl()) {
   220         if (opcode.isControl()) {
   234             binaryData.flip();
   221             binaryData.flip();
   235         }
   222         }
   236         switch (opcode) {
   223         switch (opcode) {
   237             case CLOSE:
   224             case CLOSE: