1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec.quic;
17
18 import org.jetbrains.annotations.Nullable;
19
20 final class QuicheConfig {
21 private final boolean isDatagramSupported;
22 private long config = -1;
23
24 QuicheConfig(int version,
25 @Nullable Boolean grease,
26 @Nullable Long maxIdleTimeout,
27 @Nullable Long maxSendUdpPayloadSize,
28 @Nullable Long maxRecvUdpPayloadSize,
29 @Nullable Long initialMaxData,
30 @Nullable Long initialMaxStreamDataBidiLocal,
31 @Nullable Long initialMaxStreamDataBidiRemote,
32 @Nullable Long initialMaxStreamDataUni,
33 @Nullable Long initialMaxStreamsBidi,
34 @Nullable Long initialMaxStreamsUni,
35 @Nullable Long ackDelayExponent,
36 @Nullable Long maxAckDelay,
37 @Nullable Boolean disableActiveMigration,
38 @Nullable Boolean enableHystart,
39 @Nullable QuicCongestionControlAlgorithm congestionControlAlgorithm,
40 @Nullable Integer initialCongestionWindowPackets,
41 @Nullable Integer recvQueueLen,
42 @Nullable Integer sendQueueLen,
43 @Nullable Long activeConnectionIdLimit,
44 byte @Nullable [] statelessResetToken) {
45 long config = Quiche.quiche_config_new(version);
46 try {
47 if (grease != null) {
48 Quiche.quiche_config_grease(config, grease);
49 }
50 if (maxIdleTimeout != null) {
51 Quiche.quiche_config_set_max_idle_timeout(config, maxIdleTimeout);
52 }
53 if (maxSendUdpPayloadSize != null) {
54 Quiche.quiche_config_set_max_send_udp_payload_size(config, maxSendUdpPayloadSize);
55 }
56 if (maxRecvUdpPayloadSize != null) {
57 Quiche.quiche_config_set_max_recv_udp_payload_size(config, maxRecvUdpPayloadSize);
58 }
59 if (initialMaxData != null) {
60 Quiche.quiche_config_set_initial_max_data(config, initialMaxData);
61 }
62 if (initialMaxStreamDataBidiLocal != null) {
63 Quiche.quiche_config_set_initial_max_stream_data_bidi_local(config, initialMaxStreamDataBidiLocal);
64 }
65 if (initialMaxStreamDataBidiRemote != null) {
66 Quiche.quiche_config_set_initial_max_stream_data_bidi_remote(config, initialMaxStreamDataBidiRemote);
67 }
68 if (initialMaxStreamDataUni != null) {
69 Quiche.quiche_config_set_initial_max_stream_data_uni(config, initialMaxStreamDataUni);
70 }
71 if (initialMaxStreamsBidi != null) {
72 Quiche.quiche_config_set_initial_max_streams_bidi(config, initialMaxStreamsBidi);
73 }
74 if (initialMaxStreamsUni != null) {
75 Quiche.quiche_config_set_initial_max_streams_uni(config, initialMaxStreamsUni);
76 }
77 if (ackDelayExponent != null) {
78 Quiche.quiche_config_set_ack_delay_exponent(config, ackDelayExponent);
79 }
80 if (maxAckDelay != null) {
81 Quiche.quiche_config_set_max_ack_delay(config, maxAckDelay);
82 }
83 if (disableActiveMigration != null) {
84 Quiche.quiche_config_set_disable_active_migration(config, disableActiveMigration);
85 }
86 if (enableHystart != null) {
87 Quiche.quiche_config_enable_hystart(config, enableHystart);
88 }
89 if (congestionControlAlgorithm != null) {
90 switch (congestionControlAlgorithm) {
91 case RENO:
92 Quiche.quiche_config_set_cc_algorithm(config, Quiche.QUICHE_CC_RENO);
93 break;
94 case CUBIC:
95 Quiche.quiche_config_set_cc_algorithm(config, Quiche.QUICHE_CC_CUBIC);
96 break;
97 case BBR:
98 Quiche.quiche_config_set_cc_algorithm(config, Quiche.QUICHE_CC_BBR);
99 break;
100 default:
101 throw new IllegalArgumentException(
102 "Unknown congestionControlAlgorithm: " + congestionControlAlgorithm);
103 }
104 }
105 if (initialCongestionWindowPackets != null) {
106 Quiche.quiche_config_set_initial_congestion_window_packets(config, initialCongestionWindowPackets);
107 }
108 if (recvQueueLen != null && sendQueueLen != null) {
109 isDatagramSupported = true;
110 Quiche.quiche_config_enable_dgram(config, true, recvQueueLen, sendQueueLen);
111 } else {
112 isDatagramSupported = false;
113 }
114 if (activeConnectionIdLimit != null) {
115 Quiche.quiche_config_set_active_connection_id_limit(config, activeConnectionIdLimit);
116 }
117 if (statelessResetToken != null) {
118 Quiche.quiche_config_set_stateless_reset_token(config, statelessResetToken);
119 }
120 this.config = config;
121 } catch (Throwable cause) {
122 Quiche.quiche_config_free(config);
123 throw cause;
124 }
125 }
126
127 boolean isDatagramSupported() {
128 return isDatagramSupported;
129 }
130
131 long nativeAddress() {
132 return config;
133 }
134
135
136
137 @Override
138 protected void finalize() throws Throwable {
139 try {
140 free();
141 } finally {
142 super.finalize();
143 }
144 }
145
146 void free() {
147 if (config != -1) {
148 try {
149 Quiche.quiche_config_free(config);
150 } finally {
151 config = -1;
152 }
153 }
154 }
155 }