1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.channel.epoll;
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
27 import java.io.IOException;
28 import java.net.InetAddress;
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
40 public final class EpollSocketChannelConfig extends EpollChannelConfig implements SocketChannelConfig {
41 private volatile boolean allowHalfClosure;
42 private volatile boolean tcpFastopen;
43
44
45
46
47 EpollSocketChannelConfig(EpollSocketChannel channel) {
48 super(channel);
49
50 if (PlatformDependent.canEnableTcpNoDelayByDefault()) {
51 setTcpNoDelay(true);
52 }
53 calculateMaxBytesPerGatheringWrite();
54 }
55
56 @Override
57 public Map<ChannelOption<?>, Object> getOptions() {
58 return getOptions(
59 super.getOptions(),
60 SO_RCVBUF, SO_SNDBUF, TCP_NODELAY, SO_KEEPALIVE, SO_REUSEADDR, SO_LINGER, IP_TOS,
61 ALLOW_HALF_CLOSURE, EpollChannelOption.TCP_CORK, EpollChannelOption.TCP_NOTSENT_LOWAT,
62 EpollChannelOption.TCP_KEEPCNT, EpollChannelOption.TCP_KEEPIDLE, EpollChannelOption.TCP_KEEPINTVL,
63 EpollChannelOption.TCP_MD5SIG, EpollChannelOption.TCP_QUICKACK,
64 EpollChannelOption.IP_BIND_ADDRESS_NO_PORT, EpollChannelOption.IP_TRANSPARENT,
65 ChannelOption.TCP_FASTOPEN_CONNECT, EpollChannelOption.SO_BUSY_POLL);
66 }
67
68 @SuppressWarnings("unchecked")
69 @Override
70 public <T> T getOption(ChannelOption<T> option) {
71 if (option == SO_RCVBUF) {
72 return (T) Integer.valueOf(getReceiveBufferSize());
73 }
74 if (option == SO_SNDBUF) {
75 return (T) Integer.valueOf(getSendBufferSize());
76 }
77 if (option == TCP_NODELAY) {
78 return (T) Boolean.valueOf(isTcpNoDelay());
79 }
80 if (option == SO_KEEPALIVE) {
81 return (T) Boolean.valueOf(isKeepAlive());
82 }
83 if (option == SO_REUSEADDR) {
84 return (T) Boolean.valueOf(isReuseAddress());
85 }
86 if (option == SO_LINGER) {
87 return (T) Integer.valueOf(getSoLinger());
88 }
89 if (option == IP_TOS) {
90 return (T) Integer.valueOf(getTrafficClass());
91 }
92 if (option == ALLOW_HALF_CLOSURE) {
93 return (T) Boolean.valueOf(isAllowHalfClosure());
94 }
95 if (option == EpollChannelOption.TCP_CORK) {
96 return (T) Boolean.valueOf(isTcpCork());
97 }
98 if (option == EpollChannelOption.TCP_NOTSENT_LOWAT) {
99 return (T) Long.valueOf(getTcpNotSentLowAt());
100 }
101 if (option == EpollChannelOption.TCP_KEEPIDLE) {
102 return (T) Integer.valueOf(getTcpKeepIdle());
103 }
104 if (option == EpollChannelOption.TCP_KEEPINTVL) {
105 return (T) Integer.valueOf(getTcpKeepIntvl());
106 }
107 if (option == EpollChannelOption.TCP_KEEPCNT) {
108 return (T) Integer.valueOf(getTcpKeepCnt());
109 }
110 if (option == EpollChannelOption.TCP_USER_TIMEOUT) {
111 return (T) Integer.valueOf(getTcpUserTimeout());
112 }
113 if (option == EpollChannelOption.TCP_QUICKACK) {
114 return (T) Boolean.valueOf(isTcpQuickAck());
115 }
116 if (option == EpollChannelOption.IP_BIND_ADDRESS_NO_PORT) {
117 return (T) Boolean.valueOf(isIpBindAddressNoPort());
118 }
119 if (option == EpollChannelOption.IP_TRANSPARENT) {
120 return (T) Boolean.valueOf(isIpTransparent());
121 }
122 if (option == ChannelOption.TCP_FASTOPEN_CONNECT) {
123 return (T) Boolean.valueOf(isTcpFastOpenConnect());
124 }
125 if (option == EpollChannelOption.SO_BUSY_POLL) {
126 return (T) Integer.valueOf(getSoBusyPoll());
127 }
128 return super.getOption(option);
129 }
130
131 @Override
132 public <T> boolean setOption(ChannelOption<T> option, T value) {
133 validate(option, value);
134
135 if (option == SO_RCVBUF) {
136 setReceiveBufferSize((Integer) value);
137 } else if (option == SO_SNDBUF) {
138 setSendBufferSize((Integer) value);
139 } else if (option == TCP_NODELAY) {
140 setTcpNoDelay((Boolean) value);
141 } else if (option == SO_KEEPALIVE) {
142 setKeepAlive((Boolean) value);
143 } else if (option == SO_REUSEADDR) {
144 setReuseAddress((Boolean) value);
145 } else if (option == SO_LINGER) {
146 setSoLinger((Integer) value);
147 } else if (option == IP_TOS) {
148 setTrafficClass((Integer) value);
149 } else if (option == ALLOW_HALF_CLOSURE) {
150 setAllowHalfClosure((Boolean) value);
151 } else if (option == EpollChannelOption.TCP_CORK) {
152 setTcpCork((Boolean) value);
153 } else if (option == EpollChannelOption.TCP_NOTSENT_LOWAT) {
154 setTcpNotSentLowAt((Long) value);
155 } else if (option == EpollChannelOption.TCP_KEEPIDLE) {
156 setTcpKeepIdle((Integer) value);
157 } else if (option == EpollChannelOption.TCP_KEEPCNT) {
158 setTcpKeepCnt((Integer) value);
159 } else if (option == EpollChannelOption.TCP_KEEPINTVL) {
160 setTcpKeepIntvl((Integer) value);
161 } else if (option == EpollChannelOption.TCP_USER_TIMEOUT) {
162 setTcpUserTimeout((Integer) value);
163 } else if (option == EpollChannelOption.IP_BIND_ADDRESS_NO_PORT) {
164 setIpBindAddressNoPort((Boolean) value);
165 } else if (option == EpollChannelOption.IP_TRANSPARENT) {
166 setIpTransparent((Boolean) value);
167 } else if (option == EpollChannelOption.TCP_MD5SIG) {
168 @SuppressWarnings("unchecked")
169 final Map<InetAddress, byte[]> m = (Map<InetAddress, byte[]>) value;
170 setTcpMd5Sig(m);
171 } else if (option == EpollChannelOption.TCP_QUICKACK) {
172 setTcpQuickAck((Boolean) value);
173 } else if (option == ChannelOption.TCP_FASTOPEN_CONNECT) {
174 setTcpFastOpenConnect((Boolean) value);
175 } else if (option == EpollChannelOption.SO_BUSY_POLL) {
176 setSoBusyPoll((Integer) value);
177 } else {
178 return super.setOption(option, value);
179 }
180
181 return true;
182 }
183
184 @Override
185 public int getReceiveBufferSize() {
186 try {
187 return ((EpollSocketChannel) channel).socket.getReceiveBufferSize();
188 } catch (IOException e) {
189 throw new ChannelException(e);
190 }
191 }
192
193 @Override
194 public int getSendBufferSize() {
195 try {
196 return ((EpollSocketChannel) channel).socket.getSendBufferSize();
197 } catch (IOException e) {
198 throw new ChannelException(e);
199 }
200 }
201
202 @Override
203 public int getSoLinger() {
204 try {
205 return ((EpollSocketChannel) channel).socket.getSoLinger();
206 } catch (IOException e) {
207 throw new ChannelException(e);
208 }
209 }
210
211 @Override
212 public int getTrafficClass() {
213 try {
214 return ((EpollSocketChannel) channel).socket.getTrafficClass();
215 } catch (IOException e) {
216 throw new ChannelException(e);
217 }
218 }
219
220 @Override
221 public boolean isKeepAlive() {
222 try {
223 return ((EpollSocketChannel) channel).socket.isKeepAlive();
224 } catch (IOException e) {
225 throw new ChannelException(e);
226 }
227 }
228
229 @Override
230 public boolean isReuseAddress() {
231 try {
232 return ((EpollSocketChannel) channel).socket.isReuseAddress();
233 } catch (IOException e) {
234 throw new ChannelException(e);
235 }
236 }
237
238 @Override
239 public boolean isTcpNoDelay() {
240 try {
241 return ((EpollSocketChannel) channel).socket.isTcpNoDelay();
242 } catch (IOException e) {
243 throw new ChannelException(e);
244 }
245 }
246
247
248
249
250 public boolean isTcpCork() {
251 try {
252 return ((EpollSocketChannel) channel).socket.isTcpCork();
253 } catch (IOException e) {
254 throw new ChannelException(e);
255 }
256 }
257
258
259
260
261 public int getSoBusyPoll() {
262 try {
263 return ((EpollSocketChannel) channel).socket.getSoBusyPoll();
264 } catch (IOException e) {
265 throw new ChannelException(e);
266 }
267 }
268
269
270
271
272
273 public long getTcpNotSentLowAt() {
274 try {
275 return ((EpollSocketChannel) channel).socket.getTcpNotSentLowAt();
276 } catch (IOException e) {
277 throw new ChannelException(e);
278 }
279 }
280
281
282
283
284 public int getTcpKeepIdle() {
285 try {
286 return ((EpollSocketChannel) channel).socket.getTcpKeepIdle();
287 } catch (IOException e) {
288 throw new ChannelException(e);
289 }
290 }
291
292
293
294
295 public int getTcpKeepIntvl() {
296 try {
297 return ((EpollSocketChannel) channel).socket.getTcpKeepIntvl();
298 } catch (IOException e) {
299 throw new ChannelException(e);
300 }
301 }
302
303
304
305
306 public int getTcpKeepCnt() {
307 try {
308 return ((EpollSocketChannel) channel).socket.getTcpKeepCnt();
309 } catch (IOException e) {
310 throw new ChannelException(e);
311 }
312 }
313
314
315
316
317 public int getTcpUserTimeout() {
318 try {
319 return ((EpollSocketChannel) channel).socket.getTcpUserTimeout();
320 } catch (IOException e) {
321 throw new ChannelException(e);
322 }
323 }
324
325 @Override
326 public EpollSocketChannelConfig setKeepAlive(boolean keepAlive) {
327 try {
328 ((EpollSocketChannel) channel).socket.setKeepAlive(keepAlive);
329 return this;
330 } catch (IOException e) {
331 throw new ChannelException(e);
332 }
333 }
334
335 @Override
336 public EpollSocketChannelConfig setPerformancePreferences(
337 int connectionTime, int latency, int bandwidth) {
338 return this;
339 }
340
341 @Override
342 public EpollSocketChannelConfig setReceiveBufferSize(int receiveBufferSize) {
343 try {
344 ((EpollSocketChannel) channel).socket.setReceiveBufferSize(receiveBufferSize);
345 return this;
346 } catch (IOException e) {
347 throw new ChannelException(e);
348 }
349 }
350
351 @Override
352 public EpollSocketChannelConfig setReuseAddress(boolean reuseAddress) {
353 try {
354 ((EpollSocketChannel) channel).socket.setReuseAddress(reuseAddress);
355 return this;
356 } catch (IOException e) {
357 throw new ChannelException(e);
358 }
359 }
360
361 @Override
362 public EpollSocketChannelConfig setSendBufferSize(int sendBufferSize) {
363 try {
364 ((EpollSocketChannel) channel).socket.setSendBufferSize(sendBufferSize);
365 calculateMaxBytesPerGatheringWrite();
366 return this;
367 } catch (IOException e) {
368 throw new ChannelException(e);
369 }
370 }
371
372 @Override
373 public EpollSocketChannelConfig setSoLinger(int soLinger) {
374 try {
375 ((EpollSocketChannel) channel).socket.setSoLinger(soLinger);
376 return this;
377 } catch (IOException e) {
378 throw new ChannelException(e);
379 }
380 }
381
382 @Override
383 public EpollSocketChannelConfig setTcpNoDelay(boolean tcpNoDelay) {
384 try {
385 ((EpollSocketChannel) channel).socket.setTcpNoDelay(tcpNoDelay);
386 return this;
387 } catch (IOException e) {
388 throw new ChannelException(e);
389 }
390 }
391
392
393
394
395 public EpollSocketChannelConfig setTcpCork(boolean tcpCork) {
396 try {
397 ((EpollSocketChannel) channel).socket.setTcpCork(tcpCork);
398 return this;
399 } catch (IOException e) {
400 throw new ChannelException(e);
401 }
402 }
403
404
405
406
407 public EpollSocketChannelConfig setSoBusyPoll(int loopMicros) {
408 try {
409 ((EpollSocketChannel) channel).socket.setSoBusyPoll(loopMicros);
410 return this;
411 } catch (IOException e) {
412 throw new ChannelException(e);
413 }
414 }
415
416
417
418
419
420 public EpollSocketChannelConfig setTcpNotSentLowAt(long tcpNotSentLowAt) {
421 try {
422 ((EpollSocketChannel) channel).socket.setTcpNotSentLowAt(tcpNotSentLowAt);
423 return this;
424 } catch (IOException e) {
425 throw new ChannelException(e);
426 }
427 }
428
429 @Override
430 public EpollSocketChannelConfig setTrafficClass(int trafficClass) {
431 try {
432 ((EpollSocketChannel) channel).socket.setTrafficClass(trafficClass);
433 return this;
434 } catch (IOException e) {
435 throw new ChannelException(e);
436 }
437 }
438
439
440
441
442 public EpollSocketChannelConfig setTcpKeepIdle(int seconds) {
443 try {
444 ((EpollSocketChannel) channel).socket.setTcpKeepIdle(seconds);
445 return this;
446 } catch (IOException e) {
447 throw new ChannelException(e);
448 }
449 }
450
451
452
453
454 public EpollSocketChannelConfig setTcpKeepIntvl(int seconds) {
455 try {
456 ((EpollSocketChannel) channel).socket.setTcpKeepIntvl(seconds);
457 return this;
458 } catch (IOException e) {
459 throw new ChannelException(e);
460 }
461 }
462
463
464
465
466 @Deprecated
467 public EpollSocketChannelConfig setTcpKeepCntl(int probes) {
468 return setTcpKeepCnt(probes);
469 }
470
471
472
473
474 public EpollSocketChannelConfig setTcpKeepCnt(int probes) {
475 try {
476 ((EpollSocketChannel) channel).socket.setTcpKeepCnt(probes);
477 return this;
478 } catch (IOException e) {
479 throw new ChannelException(e);
480 }
481 }
482
483
484
485
486 public EpollSocketChannelConfig setTcpUserTimeout(int milliseconds) {
487 try {
488 ((EpollSocketChannel) channel).socket.setTcpUserTimeout(milliseconds);
489 return this;
490 } catch (IOException e) {
491 throw new ChannelException(e);
492 }
493 }
494
495
496
497
498 public boolean isIpBindAddressNoPort() {
499 try {
500 return ((EpollSocketChannel) channel).socket.isIpBindAddressNoPort();
501 } catch (IOException e) {
502 throw new ChannelException(e);
503 }
504 }
505
506
507
508
509
510
511
512 public EpollSocketChannelConfig setIpBindAddressNoPort(boolean ipBindAddressNoPort) {
513 try {
514 ((EpollSocketChannel) channel).socket.setIpBindAddressNoPort(ipBindAddressNoPort);
515 return this;
516 } catch (IOException e) {
517 throw new ChannelException(e);
518 }
519 }
520
521
522
523
524
525 public boolean isIpTransparent() {
526 try {
527 return ((EpollSocketChannel) channel).socket.isIpTransparent();
528 } catch (IOException e) {
529 throw new ChannelException(e);
530 }
531 }
532
533
534
535
536
537 public EpollSocketChannelConfig setIpTransparent(boolean transparent) {
538 try {
539 ((EpollSocketChannel) channel).socket.setIpTransparent(transparent);
540 return this;
541 } catch (IOException e) {
542 throw new ChannelException(e);
543 }
544 }
545
546
547
548
549
550
551 public EpollSocketChannelConfig setTcpMd5Sig(Map<InetAddress, byte[]> keys) {
552 try {
553 ((EpollSocketChannel) channel).setTcpMd5Sig(keys);
554 return this;
555 } catch (IOException e) {
556 throw new ChannelException(e);
557 }
558 }
559
560
561
562
563
564
565 public EpollSocketChannelConfig setTcpQuickAck(boolean quickAck) {
566 try {
567 ((EpollSocketChannel) channel).socket.setTcpQuickAck(quickAck);
568 return this;
569 } catch (IOException e) {
570 throw new ChannelException(e);
571 }
572 }
573
574
575
576
577
578 public boolean isTcpQuickAck() {
579 try {
580 return ((EpollSocketChannel) channel).socket.isTcpQuickAck();
581 } catch (IOException e) {
582 throw new ChannelException(e);
583 }
584 }
585
586
587
588
589
590
591
592 public EpollSocketChannelConfig setTcpFastOpenConnect(boolean fastOpenConnect) {
593 tcpFastopen = fastOpenConnect;
594 return this;
595 }
596
597
598
599
600 public boolean isTcpFastOpenConnect() {
601 return tcpFastopen;
602 }
603
604 @Override
605 public boolean isAllowHalfClosure() {
606 return allowHalfClosure;
607 }
608
609 @Override
610 public EpollSocketChannelConfig setAllowHalfClosure(boolean allowHalfClosure) {
611 this.allowHalfClosure = allowHalfClosure;
612 return this;
613 }
614
615 @Override
616 public EpollSocketChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) {
617 super.setConnectTimeoutMillis(connectTimeoutMillis);
618 return this;
619 }
620
621 @Override
622 @Deprecated
623 public EpollSocketChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) {
624 super.setMaxMessagesPerRead(maxMessagesPerRead);
625 return this;
626 }
627
628 @Override
629 public EpollSocketChannelConfig setWriteSpinCount(int writeSpinCount) {
630 super.setWriteSpinCount(writeSpinCount);
631 return this;
632 }
633
634 @Override
635 public EpollSocketChannelConfig setAllocator(ByteBufAllocator allocator) {
636 super.setAllocator(allocator);
637 return this;
638 }
639
640 @Override
641 public EpollSocketChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) {
642 super.setRecvByteBufAllocator(allocator);
643 return this;
644 }
645
646 @Override
647 public EpollSocketChannelConfig setAutoRead(boolean autoRead) {
648 super.setAutoRead(autoRead);
649 return this;
650 }
651
652 @Override
653 public EpollSocketChannelConfig setAutoClose(boolean autoClose) {
654 super.setAutoClose(autoClose);
655 return this;
656 }
657
658 @Override
659 @Deprecated
660 public EpollSocketChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) {
661 super.setWriteBufferHighWaterMark(writeBufferHighWaterMark);
662 return this;
663 }
664
665 @Override
666 @Deprecated
667 public EpollSocketChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) {
668 super.setWriteBufferLowWaterMark(writeBufferLowWaterMark);
669 return this;
670 }
671
672 @Override
673 public EpollSocketChannelConfig setWriteBufferWaterMark(WriteBufferWaterMark writeBufferWaterMark) {
674 super.setWriteBufferWaterMark(writeBufferWaterMark);
675 return this;
676 }
677
678 @Override
679 public EpollSocketChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) {
680 super.setMessageSizeEstimator(estimator);
681 return this;
682 }
683
684 @Override
685 public EpollSocketChannelConfig setEpollMode(EpollMode mode) {
686 super.setEpollMode(mode);
687 return this;
688 }
689
690 private void calculateMaxBytesPerGatheringWrite() {
691
692 int newSendBufferSize = getSendBufferSize() << 1;
693 if (newSendBufferSize > 0) {
694 setMaxBytesPerGatheringWrite(newSendBufferSize);
695 }
696 }
697 }