mirror of
https://github.com/wanghongenpin/proxypin.git
synced 2026-03-27 06:39:45 +08:00
88 lines
3.5 KiB
Dart
88 lines
3.5 KiB
Dart
/*
|
||
* Copyright 2023 the original author or authors.
|
||
*
|
||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
* you may not use this file except in compliance with the License.
|
||
* You may obtain a copy of the License at
|
||
*
|
||
* https://www.apache.org/licenses/LICENSE-2.0
|
||
*
|
||
* Unless required by applicable law or agreed to in writing, software
|
||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
* See the License for the specific language governing permissions and
|
||
* limitations under the License.
|
||
*/
|
||
|
||
import 'package:proxypin/network/channel/channel_context.dart';
|
||
import 'package:proxypin/network/http/h2/frame.dart';
|
||
import 'package:proxypin/network/util/byte_buf.dart';
|
||
|
||
class StreamSetting {
|
||
/// 允许发送方通知远程端点用于解码头块的头压缩表的最大大小(以八位字节为单位)。
|
||
/// 初始值为4096个八位字节。
|
||
int headTableSize = 4096;
|
||
|
||
///如果一个端点接收到的这个参数设置为0,它就不能发送PUSH_PROMISE帧。
|
||
///初始值为1,表示允许服务器推送。
|
||
bool enablePush = true;
|
||
|
||
///指示发送方允许的最大并发流数。这个限制是定向的:它适用于发送方允许接收方创建的流的数量。最初,对该值没有限制。建议此值不小于100,以免不必要地限制并行性。
|
||
int? maxConcurrentStreams;
|
||
|
||
/// 指示发送方用于流级流控制的初始窗口大小(以八位字节为单位)。初始值为216-1(65,535)个八位字节。
|
||
int initialWindowSize = 65535;
|
||
|
||
///表示发送方愿意接收的最大帧有效负载的大小(以八位字节为单位)。
|
||
int maxFrameSize = 16384;
|
||
|
||
///建议设置通知对等方发送方准备接受的头列表的最大大小(以八位字节为单位)。
|
||
///该值基于头字段的未压缩大小,包括名称和值的长度(以八位字节为单位)加上每个头字段32个八位字节的开销。
|
||
int? maxHeaderListSize;
|
||
}
|
||
|
||
class SettingHandler {
|
||
static void handleSettingsFrame(ChannelContext channelContext, FrameHeader frameHeader, ByteBuf payload) {
|
||
// SETTINGS frames must have a length that is a multiple of 6 bytes
|
||
if (frameHeader.length % 6 != 0) {
|
||
throw Exception("Invalid SETTINGS frame length");
|
||
}
|
||
|
||
// If the SETTINGS frame has the ACK flag set, then it is an acknowledgement
|
||
if (frameHeader.hasAckFlag) {
|
||
// Handle SETTINGS ACK
|
||
return;
|
||
}
|
||
var setting = channelContext.setting ??= StreamSetting();
|
||
// Otherwise, it is a SETTINGS frame that carries settings
|
||
while (payload.isReadable()) {
|
||
int identifier = payload.readShort();
|
||
int value = payload.readInt();
|
||
// print("SettingHandler.handleSettingsFrame identifier=$identifier value=$value");
|
||
|
||
// Handle the setting based on its identifier
|
||
switch (identifier) {
|
||
case 1: // SETTINGS_HEADER_TABLE_SIZE
|
||
setting.headTableSize = value;
|
||
break;
|
||
case 2: // SETTINGS_ENABLE_PUSH
|
||
setting.enablePush = value == 1;
|
||
break;
|
||
case 3: // SETTINGS_MAX_CONCURRENT_STREAMS
|
||
setting.maxConcurrentStreams = value;
|
||
break;
|
||
case 4: // SETTINGS_INITIAL_WINDOW_SIZE
|
||
setting.initialWindowSize = value;
|
||
break;
|
||
case 5: // SETTINGS_MAX_FRAME_SIZE
|
||
setting.maxFrameSize = value;
|
||
break;
|
||
case 6: // SETTINGS_MAX_HEADER_LIST_SIZE
|
||
setting.maxHeaderListSize = value;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|