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 Boolean discoverPmtu,
40 @Nullable QuicCongestionControlAlgorithm congestionControlAlgorithm,
41 @Nullable Integer initialCongestionWindowPackets,
42 @Nullable Integer recvQueueLen,
43 @Nullable Integer sendQueueLen,
44 @Nullable Long activeConnectionIdLimit,
45 byte @Nullable [] statelessResetToken) {
46 long config = Quiche.quiche_config_new(version);
47 try {
48 if (grease != null) {
49 Quiche.quiche_config_grease(config, grease);
50 }
51 if (maxIdleTimeout != null) {
52 Quiche.quiche_config_set_max_idle_timeout(config, maxIdleTimeout);
53 }
54 if (maxSendUdpPayloadSize != null) {
55 Quiche.quiche_config_set_max_send_udp_payload_size(config, maxSendUdpPayloadSize);
56 }
57 if (maxRecvUdpPayloadSize != null) {
58 Quiche.quiche_config_set_max_recv_udp_payload_size(config, maxRecvUdpPayloadSize);
59 }
60 if (initialMaxData != null) {
61 Quiche.quiche_config_set_initial_max_data(config, initialMaxData);
62 }
63 if (initialMaxStreamDataBidiLocal != null) {
64 Quiche.quiche_config_set_initial_max_stream_data_bidi_local(config, initialMaxStreamDataBidiLocal);
65 }
66 if (initialMaxStreamDataBidiRemote != null) {
67 Quiche.quiche_config_set_initial_max_stream_data_bidi_remote(config, initialMaxStreamDataBidiRemote);
68 }
69 if (initialMaxStreamDataUni != null) {
70 Quiche.quiche_config_set_initial_max_stream_data_uni(config, initialMaxStreamDataUni);
71 }
72 if (initialMaxStreamsBidi != null) {
73 Quiche.quiche_config_set_initial_max_streams_bidi(config, initialMaxStreamsBidi);
74 }
75 if (initialMaxStreamsUni != null) {
76 Quiche.quiche_config_set_initial_max_streams_uni(config, initialMaxStreamsUni);
77 }
78 if (ackDelayExponent != null) {
79 Quiche.quiche_config_set_ack_delay_exponent(config, ackDelayExponent);
80 }
81 if (maxAckDelay != null) {
82 Quiche.quiche_config_set_max_ack_delay(config, maxAckDelay);
83 }
84 if (disableActiveMigration != null) {
85 Quiche.quiche_config_set_disable_active_migration(config, disableActiveMigration);
86 }
87 if (enableHystart != null) {
88 Quiche.quiche_config_enable_hystart(config, enableHystart);
89 }
90 if (discoverPmtu != null) {
91 Quiche.quiche_config_discover_pmtu(config, discoverPmtu);
92 }
93 if (congestionControlAlgorithm != null) {
94 switch (congestionControlAlgorithm) {
95 case RENO:
96 Quiche.quiche_config_set_cc_algorithm(config, Quiche.QUICHE_CC_RENO);
97 break;
98 case CUBIC:
99 Quiche.quiche_config_set_cc_algorithm(config, Quiche.QUICHE_CC_CUBIC);
100 break;
101 case BBR:
102 Quiche.quiche_config_set_cc_algorithm(config, Quiche.QUICHE_CC_BBR);
103 break;
104 default:
105 throw new IllegalArgumentException(
106 "Unknown congestionControlAlgorithm: " + congestionControlAlgorithm);
107 }
108 }
109 if (initialCongestionWindowPackets != null) {
110 Quiche.quiche_config_set_initial_congestion_window_packets(config, initialCongestionWindowPackets);
111 }
112 if (recvQueueLen != null && sendQueueLen != null) {
113 isDatagramSupported = true;
114 Quiche.quiche_config_enable_dgram(config, true, recvQueueLen, sendQueueLen);
115 } else {
116 isDatagramSupported = false;
117 }
118 if (activeConnectionIdLimit != null) {
119 Quiche.quiche_config_set_active_connection_id_limit(config, activeConnectionIdLimit);
120 }
121 if (statelessResetToken != null) {
122 Quiche.quiche_config_set_stateless_reset_token(config, statelessResetToken);
123 }
124 this.config = config;
125 } catch (Throwable cause) {
126 Quiche.quiche_config_free(config);
127 throw cause;
128 }
129 }
130
131 boolean isDatagramSupported() {
132 return isDatagramSupported;
133 }
134
135 long nativeAddress() {
136 return config;
137 }
138
139
140
141 @Override
142 protected void finalize() throws Throwable {
143 try {
144 free();
145 } finally {
146 super.finalize();
147 }
148 }
149
150 void free() {
151 if (config != -1) {
152 try {
153 Quiche.quiche_config_free(config);
154 } finally {
155 config = -1;
156 }
157 }
158 }
159 }