1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.channel.kqueue;
17
18 import io.netty.buffer.ByteBufAllocator;
19 import io.netty.channel.ChannelException;
20 import io.netty.channel.ChannelOption;
21 import io.netty.channel.MessageSizeEstimator;
22 import io.netty.channel.RecvByteBufAllocator;
23 import io.netty.channel.WriteBufferWaterMark;
24 import io.netty.channel.socket.SocketChannelConfig;
25 import io.netty.util.internal.PlatformDependent;
26 import io.netty.util.internal.UnstableApi;
27
28 import java.io.IOException;
29 import java.util.Map;
30
31 import static io.netty.channel.ChannelOption.ALLOW_HALF_CLOSURE;
32 import static io.netty.channel.ChannelOption.IP_TOS;
33 import static io.netty.channel.ChannelOption.SO_KEEPALIVE;
34 import static io.netty.channel.ChannelOption.SO_LINGER;
35 import static io.netty.channel.ChannelOption.SO_RCVBUF;
36 import static io.netty.channel.ChannelOption.SO_REUSEADDR;
37 import static io.netty.channel.ChannelOption.SO_SNDBUF;
38 import static io.netty.channel.ChannelOption.TCP_NODELAY;
39 import static io.netty.channel.kqueue.KQueueChannelOption.SO_SNDLOWAT;
40 import static io.netty.channel.kqueue.KQueueChannelOption.TCP_NOPUSH;
41
42 @UnstableApi
43 public final class KQueueSocketChannelConfig extends KQueueChannelConfig implements SocketChannelConfig {
44 private volatile boolean allowHalfClosure;
45 private volatile boolean tcpFastopen;
46
47 KQueueSocketChannelConfig(KQueueSocketChannel channel) {
48 super(channel);
49 if (PlatformDependent.canEnableTcpNoDelayByDefault()) {
50 setTcpNoDelay(true);
51 }
52 calculateMaxBytesPerGatheringWrite();
53 }
54
55 @Override
56 public Map<ChannelOption<?>, Object> getOptions() {
57 return getOptions(
58 super.getOptions(),
59 SO_RCVBUF, SO_SNDBUF, TCP_NODELAY, SO_KEEPALIVE, SO_REUSEADDR, SO_LINGER, IP_TOS,
60 ALLOW_HALF_CLOSURE, SO_SNDLOWAT, TCP_NOPUSH);
61 }
62
63 @SuppressWarnings("unchecked")
64 @Override
65 public <T> T getOption(ChannelOption<T> option) {
66 if (option == SO_RCVBUF) {
67 return (T) Integer.valueOf(getReceiveBufferSize());
68 }
69 if (option == SO_SNDBUF) {
70 return (T) Integer.valueOf(getSendBufferSize());
71 }
72 if (option == TCP_NODELAY) {
73 return (T) Boolean.valueOf(isTcpNoDelay());
74 }
75 if (option == SO_KEEPALIVE) {
76 return (T) Boolean.valueOf(isKeepAlive());
77 }
78 if (option == SO_REUSEADDR) {
79 return (T) Boolean.valueOf(isReuseAddress());
80 }
81 if (option == SO_LINGER) {
82 return (T) Integer.valueOf(getSoLinger());
83 }
84 if (option == IP_TOS) {
85 return (T) Integer.valueOf(getTrafficClass());
86 }
87 if (option == ALLOW_HALF_CLOSURE) {
88 return (T) Boolean.valueOf(isAllowHalfClosure());
89 }
90 if (option == SO_SNDLOWAT) {
91 return (T) Integer.valueOf(getSndLowAt());
92 }
93 if (option == TCP_NOPUSH) {
94 return (T) Boolean.valueOf(isTcpNoPush());
95 }
96 if (option == ChannelOption.TCP_FASTOPEN_CONNECT) {
97 return (T) Boolean.valueOf(isTcpFastOpenConnect());
98 }
99 return super.getOption(option);
100 }
101
102 @Override
103 public <T> boolean setOption(ChannelOption<T> option, T value) {
104 validate(option, value);
105
106 if (option == SO_RCVBUF) {
107 setReceiveBufferSize((Integer) value);
108 } else if (option == SO_SNDBUF) {
109 setSendBufferSize((Integer) value);
110 } else if (option == TCP_NODELAY) {
111 setTcpNoDelay((Boolean) value);
112 } else if (option == SO_KEEPALIVE) {
113 setKeepAlive((Boolean) value);
114 } else if (option == SO_REUSEADDR) {
115 setReuseAddress((Boolean) value);
116 } else if (option == SO_LINGER) {
117 setSoLinger((Integer) value);
118 } else if (option == IP_TOS) {
119 setTrafficClass((Integer) value);
120 } else if (option == ALLOW_HALF_CLOSURE) {
121 setAllowHalfClosure((Boolean) value);
122 } else if (option == SO_SNDLOWAT) {
123 setSndLowAt((Integer) value);
124 } else if (option == TCP_NOPUSH) {
125 setTcpNoPush((Boolean) value);
126 } else if (option == ChannelOption.TCP_FASTOPEN_CONNECT) {
127 setTcpFastOpenConnect((Boolean) value);
128 } else {
129 return super.setOption(option, value);
130 }
131
132 return true;
133 }
134
135 @Override
136 public int getReceiveBufferSize() {
137 try {
138 return ((KQueueSocketChannel) channel).socket.getReceiveBufferSize();
139 } catch (IOException e) {
140 throw new ChannelException(e);
141 }
142 }
143
144 @Override
145 public int getSendBufferSize() {
146 try {
147 return ((KQueueSocketChannel) channel).socket.getSendBufferSize();
148 } catch (IOException e) {
149 throw new ChannelException(e);
150 }
151 }
152
153 @Override
154 public int getSoLinger() {
155 try {
156 return ((KQueueSocketChannel) channel).socket.getSoLinger();
157 } catch (IOException e) {
158 throw new ChannelException(e);
159 }
160 }
161
162 @Override
163 public int getTrafficClass() {
164 try {
165 return ((KQueueSocketChannel) channel).socket.getTrafficClass();
166 } catch (IOException e) {
167 throw new ChannelException(e);
168 }
169 }
170
171 @Override
172 public boolean isKeepAlive() {
173 try {
174 return ((KQueueSocketChannel) channel).socket.isKeepAlive();
175 } catch (IOException e) {
176 throw new ChannelException(e);
177 }
178 }
179
180 @Override
181 public boolean isReuseAddress() {
182 try {
183 return ((KQueueSocketChannel) channel).socket.isReuseAddress();
184 } catch (IOException e) {
185 throw new ChannelException(e);
186 }
187 }
188
189 @Override
190 public boolean isTcpNoDelay() {
191 try {
192 return ((KQueueSocketChannel) channel).socket.isTcpNoDelay();
193 } catch (IOException e) {
194 throw new ChannelException(e);
195 }
196 }
197
198 public int getSndLowAt() {
199 try {
200 return ((KQueueSocketChannel) channel).socket.getSndLowAt();
201 } catch (IOException e) {
202 throw new ChannelException(e);
203 }
204 }
205
206 public void setSndLowAt(int sndLowAt) {
207 try {
208 ((KQueueSocketChannel) channel).socket.setSndLowAt(sndLowAt);
209 } catch (IOException e) {
210 throw new ChannelException(e);
211 }
212 }
213
214 public boolean isTcpNoPush() {
215 try {
216 return ((KQueueSocketChannel) channel).socket.isTcpNoPush();
217 } catch (IOException e) {
218 throw new ChannelException(e);
219 }
220 }
221
222 public void setTcpNoPush(boolean tcpNoPush) {
223 try {
224 ((KQueueSocketChannel) channel).socket.setTcpNoPush(tcpNoPush);
225 } catch (IOException e) {
226 throw new ChannelException(e);
227 }
228 }
229
230 @Override
231 public KQueueSocketChannelConfig setKeepAlive(boolean keepAlive) {
232 try {
233 ((KQueueSocketChannel) channel).socket.setKeepAlive(keepAlive);
234 return this;
235 } catch (IOException e) {
236 throw new ChannelException(e);
237 }
238 }
239
240 @Override
241 public KQueueSocketChannelConfig setReceiveBufferSize(int receiveBufferSize) {
242 try {
243 ((KQueueSocketChannel) channel).socket.setReceiveBufferSize(receiveBufferSize);
244 return this;
245 } catch (IOException e) {
246 throw new ChannelException(e);
247 }
248 }
249
250 @Override
251 public KQueueSocketChannelConfig setReuseAddress(boolean reuseAddress) {
252 try {
253 ((KQueueSocketChannel) channel).socket.setReuseAddress(reuseAddress);
254 return this;
255 } catch (IOException e) {
256 throw new ChannelException(e);
257 }
258 }
259
260 @Override
261 public KQueueSocketChannelConfig setSendBufferSize(int sendBufferSize) {
262 try {
263 ((KQueueSocketChannel) channel).socket.setSendBufferSize(sendBufferSize);
264 calculateMaxBytesPerGatheringWrite();
265 return this;
266 } catch (IOException e) {
267 throw new ChannelException(e);
268 }
269 }
270
271 @Override
272 public KQueueSocketChannelConfig setSoLinger(int soLinger) {
273 try {
274 ((KQueueSocketChannel) channel).socket.setSoLinger(soLinger);
275 return this;
276 } catch (IOException e) {
277 throw new ChannelException(e);
278 }
279 }
280
281 @Override
282 public KQueueSocketChannelConfig setTcpNoDelay(boolean tcpNoDelay) {
283 try {
284 ((KQueueSocketChannel) channel).socket.setTcpNoDelay(tcpNoDelay);
285 return this;
286 } catch (IOException e) {
287 throw new ChannelException(e);
288 }
289 }
290
291 @Override
292 public KQueueSocketChannelConfig setTrafficClass(int trafficClass) {
293 try {
294 ((KQueueSocketChannel) channel).socket.setTrafficClass(trafficClass);
295 return this;
296 } catch (IOException e) {
297 throw new ChannelException(e);
298 }
299 }
300
301 @Override
302 public boolean isAllowHalfClosure() {
303 return allowHalfClosure;
304 }
305
306
307
308
309 public KQueueSocketChannelConfig setTcpFastOpenConnect(boolean fastOpenConnect) {
310 tcpFastopen = fastOpenConnect;
311 return this;
312 }
313
314
315
316
317 public boolean isTcpFastOpenConnect() {
318 return tcpFastopen;
319 }
320
321 @Override
322 public KQueueSocketChannelConfig setRcvAllocTransportProvidesGuess(boolean transportProvidesGuess) {
323 super.setRcvAllocTransportProvidesGuess(transportProvidesGuess);
324 return this;
325 }
326
327 @Override
328 public KQueueSocketChannelConfig setPerformancePreferences(
329 int connectionTime, int latency, int bandwidth) {
330 return this;
331 }
332
333 @Override
334 public KQueueSocketChannelConfig setAllowHalfClosure(boolean allowHalfClosure) {
335 this.allowHalfClosure = allowHalfClosure;
336 return this;
337 }
338
339 @Override
340 public KQueueSocketChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) {
341 super.setConnectTimeoutMillis(connectTimeoutMillis);
342 return this;
343 }
344
345 @Override
346 @Deprecated
347 public KQueueSocketChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) {
348 super.setMaxMessagesPerRead(maxMessagesPerRead);
349 return this;
350 }
351
352 @Override
353 public KQueueSocketChannelConfig setWriteSpinCount(int writeSpinCount) {
354 super.setWriteSpinCount(writeSpinCount);
355 return this;
356 }
357
358 @Override
359 public KQueueSocketChannelConfig setAllocator(ByteBufAllocator allocator) {
360 super.setAllocator(allocator);
361 return this;
362 }
363
364 @Override
365 public KQueueSocketChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) {
366 super.setRecvByteBufAllocator(allocator);
367 return this;
368 }
369
370 @Override
371 public KQueueSocketChannelConfig setAutoRead(boolean autoRead) {
372 super.setAutoRead(autoRead);
373 return this;
374 }
375
376 @Override
377 public KQueueSocketChannelConfig setAutoClose(boolean autoClose) {
378 super.setAutoClose(autoClose);
379 return this;
380 }
381
382 @Override
383 @Deprecated
384 public KQueueSocketChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) {
385 super.setWriteBufferHighWaterMark(writeBufferHighWaterMark);
386 return this;
387 }
388
389 @Override
390 @Deprecated
391 public KQueueSocketChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) {
392 super.setWriteBufferLowWaterMark(writeBufferLowWaterMark);
393 return this;
394 }
395
396 @Override
397 public KQueueSocketChannelConfig setWriteBufferWaterMark(WriteBufferWaterMark writeBufferWaterMark) {
398 super.setWriteBufferWaterMark(writeBufferWaterMark);
399 return this;
400 }
401
402 @Override
403 public KQueueSocketChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) {
404 super.setMessageSizeEstimator(estimator);
405 return this;
406 }
407
408 private void calculateMaxBytesPerGatheringWrite() {
409
410 int newSendBufferSize = getSendBufferSize() << 1;
411 if (newSendBufferSize > 0) {
412 setMaxBytesPerGatheringWrite(newSendBufferSize);
413 }
414 }
415 }