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