1 /*
2 * Copyright 2020 The Netty Project
3 *
4 * The Netty Project licenses this file to you under the Apache License,
5 * version 2.0 (the "License"); you may not use this file except in compliance
6 * with the License. You may obtain a copy of the License at:
7 *
8 * https://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, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16 package io.netty.handler.codec.quic;
17
18 import io.netty.channel.ChannelHandler;
19 import io.netty.channel.ChannelOption;
20 import io.netty.util.AttributeKey;
21 import io.netty.util.internal.ObjectUtil;
22 import org.jetbrains.annotations.Nullable;
23
24 import java.util.HashMap;
25 import java.util.LinkedHashMap;
26 import java.util.Map;
27 import java.util.concurrent.Executor;
28 import java.util.function.Function;
29
30 /**
31 * {@link QuicCodecBuilder} that configures and builds a {@link ChannelHandler} that should be added to the
32 * {@link io.netty.channel.ChannelPipeline} of a {@code QUIC} server.
33 */
34 public final class QuicServerCodecBuilder extends QuicCodecBuilder<QuicServerCodecBuilder> {
35 // The order in which ChannelOptions are applied is important they may depend on each other for validation
36 // purposes.
37 private final Map<ChannelOption<?>, Object> options = new LinkedHashMap<>();
38 private final Map<AttributeKey<?>, Object> attrs = new HashMap<>();
39 private final Map<ChannelOption<?>, Object> streamOptions = new LinkedHashMap<>();
40 private final Map<AttributeKey<?>, Object> streamAttrs = new HashMap<>();
41 private ChannelHandler handler;
42 private ChannelHandler streamHandler;
43 private QuicConnectionIdGenerator connectionIdAddressGenerator;
44 private QuicTokenHandler tokenHandler;
45 private QuicResetTokenGenerator resetTokenGenerator;
46
47 /**
48 * Creates a new instance.
49 */
50 public QuicServerCodecBuilder() {
51 super(true);
52 }
53
54 private QuicServerCodecBuilder(QuicServerCodecBuilder builder) {
55 super(builder);
56 options.putAll(builder.options);
57 attrs.putAll(builder.attrs);
58 streamOptions.putAll(builder.streamOptions);
59 streamAttrs.putAll(builder.streamAttrs);
60 handler = builder.handler;
61 streamHandler = builder.streamHandler;
62 connectionIdAddressGenerator = builder.connectionIdAddressGenerator;
63 tokenHandler = builder.tokenHandler;
64 resetTokenGenerator = builder.resetTokenGenerator;
65 }
66
67 @Override
68 public QuicServerCodecBuilder clone() {
69 return new QuicServerCodecBuilder(this);
70 }
71
72 /**
73 * Allow to specify a {@link ChannelOption} which is used for the {@link QuicChannel} instances once they got
74 * created. Use a value of {@code null} to remove a previous set {@link ChannelOption}.
75 *
76 * @param option the {@link ChannelOption} to apply to the {@link QuicChannel}.
77 * @param value the value of the option.
78 * @param <T> the type of the value.
79 * @return this instance.
80 */
81 public <T> QuicServerCodecBuilder option(ChannelOption<T> option, @Nullable T value) {
82 Quic.updateOptions(options, option, value);
83 return self();
84 }
85
86 /**
87 * Allow to specify an initial attribute of the newly created {@link QuicChannel}. If the {@code value} is
88 * {@code null}, the attribute of the specified {@code key} is removed.
89 *
90 * @param key the {@link AttributeKey} to apply to the {@link QuicChannel}.
91 * @param value the value of the attribute.
92 * @param <T> the type of the value.
93 * @return this instance.
94 */
95 public <T> QuicServerCodecBuilder attr(AttributeKey<T> key, @Nullable T value) {
96 Quic.updateAttributes(attrs, key, value);
97 return self();
98 }
99
100 /**
101 * Set the {@link ChannelHandler} that is added to the {@link io.netty.channel.ChannelPipeline} of the
102 * {@link QuicChannel} once created.
103 *
104 * @param handler the {@link ChannelHandler} that is added to the {@link QuicChannel}s
105 * {@link io.netty.channel.ChannelPipeline}.
106 * @return this instance.
107 */
108 public QuicServerCodecBuilder handler(ChannelHandler handler) {
109 this.handler = ObjectUtil.checkNotNull(handler, "handler");
110 return self();
111 }
112
113 /**
114 * Allow to specify a {@link ChannelOption} which is used for the {@link QuicStreamChannel} instances once they got
115 * created. Use a value of {@code null} to remove a previous set {@link ChannelOption}.
116 *
117 * @param option the {@link ChannelOption} to apply to the {@link QuicStreamChannel}s.
118 * @param value the value of the option.
119 * @param <T> the type of the value.
120 * @return this instance.
121 */
122 public <T> QuicServerCodecBuilder streamOption(ChannelOption<T> option, @Nullable T value) {
123 Quic.updateOptions(streamOptions, option, value);
124 return self();
125 }
126
127 /**
128 * Allow to specify an initial attribute of the newly created {@link QuicStreamChannel}. If the {@code value} is
129 * {@code null}, the attribute of the specified {@code key} is removed.
130 *
131 * @param key the {@link AttributeKey} to apply to the {@link QuicStreamChannel}s.
132 * @param value the value of the attribute.
133 * @param <T> the type of the value.
134 * @return this instance.
135 */
136 public <T> QuicServerCodecBuilder streamAttr(AttributeKey<T> key, @Nullable T value) {
137 Quic.updateAttributes(streamAttrs, key, value);
138 return self();
139 }
140
141 /**
142 * Set the {@link ChannelHandler} that is added to the {@link io.netty.channel.ChannelPipeline} of the
143 * {@link QuicStreamChannel} once created.
144 *
145 * @param streamHandler the {@link ChannelHandler} that is added to the {@link QuicStreamChannel}s
146 * {@link io.netty.channel.ChannelPipeline}.
147 * @return this instance.
148 */
149 public QuicServerCodecBuilder streamHandler(ChannelHandler streamHandler) {
150 this.streamHandler = ObjectUtil.checkNotNull(streamHandler, "streamHandler");
151 return self();
152 }
153
154 /**
155 * Sets the {@link QuicConnectionIdGenerator} to use.
156 *
157 * @param connectionIdAddressGenerator the {@link QuicConnectionIdGenerator} to use.
158 * @return this instance.
159 */
160 public QuicServerCodecBuilder connectionIdAddressGenerator(
161 QuicConnectionIdGenerator connectionIdAddressGenerator) {
162 this.connectionIdAddressGenerator = connectionIdAddressGenerator;
163 return this;
164 }
165
166 /**
167 * Set the {@link QuicTokenHandler} that is used to generate and validate tokens or
168 * {@code null} if no tokens should be used at all.
169 *
170 * @param tokenHandler the {@link QuicTokenHandler} to use.
171 * @return this instance.
172 */
173 public QuicServerCodecBuilder tokenHandler(@Nullable QuicTokenHandler tokenHandler) {
174 this.tokenHandler = tokenHandler;
175 return self();
176 }
177
178 /**
179 * Set the {@link QuicResetTokenGenerator} that is used to generate stateless reset tokens or
180 * {@code null} if the default should be used.
181 *
182 * @param resetTokenGenerator the {@link QuicResetTokenGenerator} to use.
183 * @return this instance.
184 */
185 public QuicServerCodecBuilder resetTokenGenerator(@Nullable QuicResetTokenGenerator resetTokenGenerator) {
186 this.resetTokenGenerator = resetTokenGenerator;
187 return self();
188 }
189
190 @Override
191 protected void validate() {
192 super.validate();
193 if (handler == null && streamHandler == null) {
194 throw new IllegalStateException("handler and streamHandler not set");
195 }
196 }
197
198 @Override
199 ChannelHandler build(QuicheConfig config,
200 Function<QuicChannel, ? extends QuicSslEngine> sslEngineProvider,
201 Executor sslTaskExecutor,
202 int localConnIdLength, FlushStrategy flushStrategy) {
203 validate();
204 QuicTokenHandler tokenHandler = this.tokenHandler;
205 if (tokenHandler == null) {
206 tokenHandler = NoQuicTokenHandler.INSTANCE;
207 }
208 QuicConnectionIdGenerator generator = connectionIdAddressGenerator;
209 if (generator == null) {
210 generator = QuicConnectionIdGenerator.signGenerator();
211 }
212 QuicResetTokenGenerator resetTokenGenerator = this.resetTokenGenerator;
213 if (resetTokenGenerator == null) {
214 resetTokenGenerator = QuicResetTokenGenerator.signGenerator();
215 }
216 ChannelHandler handler = this.handler;
217 ChannelHandler streamHandler = this.streamHandler;
218 return new QuicheQuicServerCodec(config, localConnIdLength, tokenHandler, generator, resetTokenGenerator,
219 flushStrategy, sslEngineProvider, sslTaskExecutor, handler,
220 Quic.toOptionsArray(options), Quic.toAttributesArray(attrs),
221 streamHandler, Quic.toOptionsArray(streamOptions), Quic.toAttributesArray(streamAttrs));
222 }
223 }