View Javadoc
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 }