Home | History | Annotate | Download | only in ws
      1 /*
      2  * Copyright (C) 2014 Square, Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.squareup.okhttp.internal.ws;
     17 
     18 public final class WebSocketProtocol {
     19   /** Magic value which must be appended to the key in a response header. */
     20   public static final String ACCEPT_MAGIC = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
     21 
     22   /*
     23   Each frame starts with two bytes of data.
     24 
     25    0 1 2 3 4 5 6 7    0 1 2 3 4 5 6 7
     26   +-+-+-+-+-------+  +-+-------------+
     27   |F|R|R|R| OP    |  |M| LENGTH      |
     28   |I|S|S|S| CODE  |  |A|             |
     29   |N|V|V|V|       |  |S|             |
     30   | |1|2|3|       |  |K|             |
     31   +-+-+-+-+-------+  +-+-------------+
     32   */
     33 
     34   /** Byte 0 flag for whether this is the final fragment in a message. */
     35   static final int B0_FLAG_FIN = 0b10000000;
     36   /** Byte 0 reserved flag 1. Must be 0 unless negotiated otherwise. */
     37   static final int B0_FLAG_RSV1 = 0b01000000;
     38   /** Byte 0 reserved flag 2. Must be 0 unless negotiated otherwise. */
     39   static final int B0_FLAG_RSV2 = 0b00100000;
     40   /** Byte 0 reserved flag 3. Must be 0 unless negotiated otherwise. */
     41   static final int B0_FLAG_RSV3 = 0b00010000;
     42   /** Byte 0 mask for the frame opcode. */
     43   static final int B0_MASK_OPCODE = 0b00001111;
     44   /** Flag in the opcode which indicates a control frame. */
     45   static final int OPCODE_FLAG_CONTROL = 0b00001000;
     46 
     47   /**
     48    * Byte 1 flag for whether the payload data is masked.
     49    * <p>
     50    * If this flag is set, the next four bytes represent the mask key. These bytes appear after
     51    * any additional bytes specified by {@link #B1_MASK_LENGTH}.
     52    */
     53   static final int B1_FLAG_MASK = 0b10000000;
     54   /**
     55    * Byte 1 mask for the payload length.
     56    * <p>
     57    * If this value is {@link #PAYLOAD_SHORT}, the next two bytes represent the length.
     58    * If this value is {@link #PAYLOAD_LONG}, the next eight bytes represent the length.
     59    */
     60   static final int B1_MASK_LENGTH = 0b01111111;
     61 
     62   static final int OPCODE_CONTINUATION = 0x0;
     63   static final int OPCODE_TEXT = 0x1;
     64   static final int OPCODE_BINARY = 0x2;
     65 
     66   static final int OPCODE_CONTROL_CLOSE = 0x8;
     67   static final int OPCODE_CONTROL_PING = 0x9;
     68   static final int OPCODE_CONTROL_PONG = 0xa;
     69 
     70   /**
     71    * Maximum length of frame payload. Larger payloads, if supported, can use the special values
     72    * {@link #PAYLOAD_SHORT} or {@link #PAYLOAD_LONG}.
     73    */
     74   static final int PAYLOAD_MAX = 125;
     75   /**
     76    * Value for {@link #B1_MASK_LENGTH} which indicates the next two bytes are the unsigned length.
     77    */
     78   static final int PAYLOAD_SHORT = 126;
     79   /**
     80    * Value for {@link #B1_MASK_LENGTH} which indicates the next eight bytes are the unsigned
     81    * length.
     82    */
     83   static final int PAYLOAD_LONG = 127;
     84 
     85   static void toggleMask(byte[] buffer, long byteCount, byte[] key, long frameBytesRead) {
     86     int keyLength = key.length;
     87     for (int i = 0; i < byteCount; i++, frameBytesRead++) {
     88       int keyIndex = (int) (frameBytesRead % keyLength);
     89       buffer[i] = (byte) (buffer[i] ^ key[keyIndex]);
     90     }
     91   }
     92 
     93   private WebSocketProtocol() {
     94     throw new AssertionError("No instances.");
     95   }
     96 }
     97