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