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.buffer.ByteBufAllocator;
19  import io.netty.channel.ChannelOption;
20  import io.netty.channel.DefaultChannelConfig;
21  import io.netty.channel.MessageSizeEstimator;
22  import io.netty.channel.RecvByteBufAllocator;
23  import io.netty.channel.WriteBufferWaterMark;
24  
25  import java.util.Map;
26  
27  final class QuicheQuicStreamChannelConfig extends DefaultChannelConfig implements QuicStreamChannelConfig {
28      // We should use half-closure sementatics by default as this is what QUIC does by default.
29      // If you receive a FIN you should still keep the stream open until you write a FIN as well.
30      private volatile boolean allowHalfClosure = true;
31      private volatile boolean readFrames;
32      volatile DirectIoByteBufAllocator allocator;
33  
34      QuicheQuicStreamChannelConfig(QuicStreamChannel channel) {
35          super(channel);
36          allocator = new DirectIoByteBufAllocator(super.getAllocator());
37      }
38  
39      @Override
40      public Map<ChannelOption<?>, Object> getOptions() {
41          if (isHalfClosureSupported()) {
42              return getOptions(super.getOptions(), ChannelOption.ALLOW_HALF_CLOSURE, QuicChannelOption.READ_FRAMES);
43          }
44          return super.getOptions();
45      }
46  
47      @SuppressWarnings("unchecked")
48      @Override
49      public <T> T getOption(ChannelOption<T> option) {
50          if (option == ChannelOption.ALLOW_HALF_CLOSURE) {
51              return (T) Boolean.valueOf(isAllowHalfClosure());
52          }
53          if (option == QuicChannelOption.READ_FRAMES) {
54              return (T) Boolean.valueOf(isReadFrames());
55          }
56          return super.getOption(option);
57      }
58  
59      @Override
60      public <T> boolean setOption(ChannelOption<T> option, T value) {
61          validate(option, value);
62  
63          if (option == ChannelOption.ALLOW_HALF_CLOSURE) {
64              if (isHalfClosureSupported()) {
65                  setAllowHalfClosure((Boolean) value);
66                  return true;
67              }
68              return false;
69          }
70          if (option == QuicChannelOption.READ_FRAMES) {
71              setReadFrames((Boolean) value);
72          }
73          return super.setOption(option, value);
74      }
75  
76      @Override
77      public QuicStreamChannelConfig setReadFrames(boolean readFrames) {
78          this.readFrames = readFrames;
79          return this;
80      }
81  
82      @Override
83      public boolean isReadFrames() {
84          return readFrames;
85      }
86  
87      @Override
88      public QuicStreamChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) {
89          super.setConnectTimeoutMillis(connectTimeoutMillis);
90          return this;
91      }
92  
93      @Override
94      public QuicStreamChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) {
95          super.setMaxMessagesPerRead(maxMessagesPerRead);
96          return this;
97      }
98  
99      @Override
100     public QuicStreamChannelConfig setWriteSpinCount(int writeSpinCount) {
101         super.setWriteSpinCount(writeSpinCount);
102         return this;
103     }
104 
105     @Override
106     public QuicStreamChannelConfig setAllocator(ByteBufAllocator allocator) {
107         this.allocator = new DirectIoByteBufAllocator(allocator);
108         return this;
109     }
110 
111     @Override
112     public QuicStreamChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) {
113         super.setRecvByteBufAllocator(allocator);
114         return this;
115     }
116 
117     @Override
118     public QuicStreamChannelConfig setAutoRead(boolean autoRead) {
119         super.setAutoRead(autoRead);
120         return this;
121     }
122 
123     @Override
124     public QuicStreamChannelConfig setAutoClose(boolean autoClose) {
125         super.setAutoClose(autoClose);
126         return this;
127     }
128 
129     @Override
130     public QuicStreamChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) {
131         super.setWriteBufferHighWaterMark(writeBufferHighWaterMark);
132         return this;
133     }
134 
135     @Override
136     public QuicStreamChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) {
137         super.setWriteBufferLowWaterMark(writeBufferLowWaterMark);
138         return this;
139     }
140 
141     @Override
142     public QuicStreamChannelConfig setWriteBufferWaterMark(WriteBufferWaterMark writeBufferWaterMark) {
143         super.setWriteBufferWaterMark(writeBufferWaterMark);
144         return this;
145     }
146 
147     @Override
148     public QuicStreamChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) {
149         super.setMessageSizeEstimator(estimator);
150         return this;
151     }
152 
153     @Override
154     public QuicStreamChannelConfig setAllowHalfClosure(boolean allowHalfClosure) {
155         if (!isHalfClosureSupported()) {
156             throw new UnsupportedOperationException("Undirectional streams don't support half-closure");
157         }
158         this.allowHalfClosure = allowHalfClosure;
159         return this;
160     }
161 
162     @Override
163     public ByteBufAllocator getAllocator() {
164         return allocator.wrapped();
165     }
166 
167     @Override
168     public boolean isAllowHalfClosure() {
169         return allowHalfClosure;
170     }
171 
172     private boolean isHalfClosureSupported() {
173         return ((QuicStreamChannel) channel).type() == QuicStreamType.BIDIRECTIONAL;
174     }
175 }