org.aoju.bus.http.socket.WebSocketProtocol Maven / Gradle / Ivy
The newest version!
/*********************************************************************************
* *
* The MIT License (MIT) *
* *
* Copyright (c) 2015-2022 aoju.org and other contributors. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy *
* of this software and associated documentation files (the "Software"), to deal *
* in the Software without restriction, including without limitation the rights *
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell *
* copies of the Software, and to permit persons to whom the Software is *
* furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN *
* THE SOFTWARE. *
* *
********************************************************************************/
package org.aoju.bus.http.socket;
import org.aoju.bus.core.io.ByteString;
import org.aoju.bus.core.io.buffer.Buffer;
/**
* web socket协议信息
*
* @author Kimi Liu
* @since Java 17+
*/
public class WebSocketProtocol {
/**
* 须附加到响应标头中的键的魔法值
*/
static final String ACCEPT_MAGIC = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
/**
* 标记这是否是消息中的最后一个片段
*/
static final int B0_FLAG_FIN = 0b10000000;
/**
* 保留标志1。必须是0
*/
static final int B0_FLAG_RSV1 = 0b01000000;
/**
* 保留标志2。必须是0
*/
static final int B0_FLAG_RSV2 = 0b00100000;
/**
* 保留标志3。必须是0
*/
static final int B0_FLAG_RSV3 = 0b00010000;
/**
* 帧操作码的字节0掩码
*/
static final int B0_MASK_OPCODE = 0b00001111;
/**
* 在操作码中标记,指示控制帧
*/
static final int OPCODE_FLAG_CONTROL = 0b00001000;
/**
* 字节1标记是否屏蔽了有效负载数据
* 如果设置了这个标志,接下来的四个字节表示掩码键
* 这些字节出现在{@link #B1_MASK_LENGTH}指定的任何附加字节之后
*/
static final int B1_FLAG_MASK = 0b10000000;
/**
* 有效负载长度的字节1掩码
* 如果这个值是{@link #PAYLOAD_SHORT},接下来的两个字节表示长度
* 如果这个值是{@link #PAYLOAD_LONG},接下来的8个字节表示长度
*/
static final int B1_MASK_LENGTH = 0b01111111;
static final int OPCODE_CONTINUATION = 0x0;
static final int OPCODE_TEXT = 0x1;
static final int OPCODE_BINARY = 0x2;
static final int OPCODE_CONTROL_CLOSE = 0x8;
static final int OPCODE_CONTROL_PING = 0x9;
static final int OPCODE_CONTROL_PONG = 0xa;
/**
* 帧有效载荷的最大长度。如果框架类型支持较大的有效负载,
* 则可以使用特殊值{@link #PAYLOAD_SHORT}或{@link #PAYLOAD_LONG}
*/
static final long PAYLOAD_BYTE_MAX = 125L;
/**
* 关闭消息的最大长度(以字节为单位)
*/
static final long CLOSE_MESSAGE_MAX = PAYLOAD_BYTE_MAX - 2;
/**
* 表示后面两个字节是无符号长度的{@link #B1_MASK_LENGTH}的值
*/
static final int PAYLOAD_SHORT = 126;
/**
* 帧有效载荷的最大长度表示为{@link #PAYLOAD_SHORT}
*/
static final long PAYLOAD_SHORT_MAX = 0xffffL;
/**
* {@link #B1_MASK_LENGTH}的值,该值指示接下来的八个字节是无符号长度
*/
static final int PAYLOAD_LONG = 127;
/**
* 在侦听器中抛出未检查异常时使用
*/
static final int CLOSE_CLIENT_GOING_AWAY = 1001;
/**
* 当接收到一个空的关闭帧时使用,没有状态码)
*/
static final int CLOSE_NO_STATUS_CODE = 1005;
private WebSocketProtocol() {
throw new AssertionError("No instances.");
}
static void toggleMask(Buffer.UnsafeCursor cursor, byte[] key) {
int keyIndex = 0;
int keyLength = key.length;
do {
byte[] buffer = cursor.data;
for (int i = cursor.start, end = cursor.end; i < end; i++, keyIndex++) {
keyIndex %= keyLength;
buffer[i] = (byte) (buffer[i] ^ key[keyIndex]);
}
} while (cursor.next() != -1);
}
static String closeCodeExceptionMessage(int code) {
if (code < 1000 || code >= 5000) {
return "Code must be in range [1000,5000): " + code;
} else if ((code >= 1004 && code <= 1006) || (code >= 1012 && code <= 2999)) {
return "Code " + code + " is reserved and may not be used.";
} else {
return null;
}
}
static void validateCloseCode(int code) {
String message = closeCodeExceptionMessage(code);
if (null != message) throw new IllegalArgumentException(message);
}
public static String acceptHeader(String key) {
return ByteString.encodeUtf8(key + WebSocketProtocol.ACCEPT_MAGIC).sha1().base64();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy