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.socket.SocketChannelConfig;
24 import io.netty.util.internal.PlatformDependent;
25
26 import java.io.IOException;
27 import java.net.InetAddress;
28 import java.util.Map;
29
30 import static io.netty.channel.ChannelOption.*;
31
32 public final class EpollSocketChannelConfig extends EpollChannelConfig implements SocketChannelConfig {
33 private static final long MAX_UINT32_T = 0xFFFFFFFFL;
34 private final EpollSocketChannel channel;
35 private volatile boolean allowHalfClosure;
36
37
38
39
40 EpollSocketChannelConfig(EpollSocketChannel channel) {
41 super(channel);
42
43 this.channel = channel;
44 if (PlatformDependent.canEnableTcpNoDelayByDefault()) {
45 setTcpNoDelay(true);
46 }
47
48 setMaxMessagesPerRead(16);
49 }
50
51 @Override
52 public Map<ChannelOption<?>, Object> getOptions() {
53 return getOptions(
54 super.getOptions(),
55 SO_RCVBUF, SO_SNDBUF, TCP_NODELAY, SO_KEEPALIVE, SO_REUSEADDR, SO_LINGER, IP_TOS,
56 ALLOW_HALF_CLOSURE, EpollChannelOption.TCP_CORK, EpollChannelOption.TCP_NOTSENT_LOWAT,
57 EpollChannelOption.TCP_KEEPCNT, EpollChannelOption.TCP_KEEPIDLE, EpollChannelOption.TCP_KEEPINTVL,
58 EpollChannelOption.TCP_MD5SIG, EpollChannelOption.TCP_QUICKACK);
59 }
60
61 @SuppressWarnings("unchecked")
62 @Override
63 public <T> T getOption(ChannelOption<T> option) {
64 if (option == SO_RCVBUF) {
65 return (T) Integer.valueOf(getReceiveBufferSize());
66 }
67 if (option == SO_SNDBUF) {
68 return (T) Integer.valueOf(getSendBufferSize());
69 }
70 if (option == TCP_NODELAY) {
71 return (T) Boolean.valueOf(isTcpNoDelay());
72 }
73 if (option == SO_KEEPALIVE) {
74 return (T) Boolean.valueOf(isKeepAlive());
75 }
76 if (option == SO_REUSEADDR) {
77 return (T) Boolean.valueOf(isReuseAddress());
78 }
79 if (option == SO_LINGER) {
80 return (T) Integer.valueOf(getSoLinger());
81 }
82 if (option == IP_TOS) {
83 return (T) Integer.valueOf(getTrafficClass());
84 }
85 if (option == ALLOW_HALF_CLOSURE) {
86 return (T) Boolean.valueOf(isAllowHalfClosure());
87 }
88 if (option == EpollChannelOption.TCP_CORK) {
89 return (T) Boolean.valueOf(isTcpCork());
90 }
91 if (option == EpollChannelOption.TCP_NOTSENT_LOWAT) {
92 return (T) Long.valueOf(getTcpNotSentLowAt());
93 }
94 if (option == EpollChannelOption.TCP_KEEPIDLE) {
95 return (T) Integer.valueOf(getTcpKeepIdle());
96 }
97 if (option == EpollChannelOption.TCP_KEEPINTVL) {
98 return (T) Integer.valueOf(getTcpKeepIntvl());
99 }
100 if (option == EpollChannelOption.TCP_KEEPCNT) {
101 return (T) Integer.valueOf(getTcpKeepCnt());
102 }
103 if (option == EpollChannelOption.TCP_USER_TIMEOUT) {
104 return (T) Integer.valueOf(getTcpUserTimeout());
105 }
106 if (option == EpollChannelOption.TCP_QUICKACK) {
107 return (T) Boolean.valueOf(isTcpQuickAck());
108 }
109 return super.getOption(option);
110 }
111
112 @Override
113 public <T> boolean setOption(ChannelOption<T> option, T value) {
114 validate(option, value);
115
116 if (option == SO_RCVBUF) {
117 setReceiveBufferSize((Integer) value);
118 } else if (option == SO_SNDBUF) {
119 setSendBufferSize((Integer) value);
120 } else if (option == TCP_NODELAY) {
121 setTcpNoDelay((Boolean) value);
122 } else if (option == SO_KEEPALIVE) {
123 setKeepAlive((Boolean) value);
124 } else if (option == SO_REUSEADDR) {
125 setReuseAddress((Boolean) value);
126 } else if (option == SO_LINGER) {
127 setSoLinger((Integer) value);
128 } else if (option == IP_TOS) {
129 setTrafficClass((Integer) value);
130 } else if (option == ALLOW_HALF_CLOSURE) {
131 setAllowHalfClosure((Boolean) value);
132 } else if (option == EpollChannelOption.TCP_CORK) {
133 setTcpCork((Boolean) value);
134 } else if (option == EpollChannelOption.TCP_NOTSENT_LOWAT) {
135 setTcpNotSentLowAt((Long) value);
136 } else if (option == EpollChannelOption.TCP_KEEPIDLE) {
137 setTcpKeepIdle((Integer) value);
138 } else if (option == EpollChannelOption.TCP_KEEPCNT) {
139 setTcpKeepCnt((Integer) value);
140 } else if (option == EpollChannelOption.TCP_KEEPINTVL) {
141 setTcpKeepIntvl((Integer) value);
142 } else if (option == EpollChannelOption.TCP_USER_TIMEOUT) {
143 setTcpUserTimeout((Integer) value);
144 } else if (option == EpollChannelOption.TCP_MD5SIG) {
145 @SuppressWarnings("unchecked")
146 final Map<InetAddress, byte[]> m = (Map<InetAddress, byte[]>) value;
147 setTcpMd5Sig(m);
148 } else if (option == EpollChannelOption.TCP_QUICKACK) {
149 setTcpQuickAck((Boolean) value);
150 } else {
151 return super.setOption(option, value);
152 }
153
154 return true;
155 }
156
157 @Override
158 public int getReceiveBufferSize() {
159 try {
160 return channel.fd().getReceiveBufferSize();
161 } catch (IOException e) {
162 throw new ChannelException(e);
163 }
164 }
165
166 @Override
167 public int getSendBufferSize() {
168 try {
169 return channel.fd().getSendBufferSize();
170 } catch (IOException e) {
171 throw new ChannelException(e);
172 }
173 }
174
175 @Override
176 public int getSoLinger() {
177 try {
178 return channel.fd().getSoLinger();
179 } catch (IOException e) {
180 throw new ChannelException(e);
181 }
182 }
183
184 @Override
185 public int getTrafficClass() {
186 try {
187 return Native.getTrafficClass(channel.fd().intValue());
188 } catch (IOException e) {
189 throw new ChannelException(e);
190 }
191 }
192
193 @Override
194 public boolean isKeepAlive() {
195 try {
196 return channel.fd().isKeepAlive();
197 } catch (IOException e) {
198 throw new ChannelException(e);
199 }
200 }
201
202 @Override
203 public boolean isReuseAddress() {
204 try {
205 return Native.isReuseAddress(channel.fd().intValue()) == 1;
206 } catch (IOException e) {
207 throw new ChannelException(e);
208 }
209 }
210
211 @Override
212 public boolean isTcpNoDelay() {
213 try {
214 return channel.fd().isTcpNoDelay();
215 } catch (IOException e) {
216 throw new ChannelException(e);
217 }
218 }
219
220
221
222
223 public boolean isTcpCork() {
224 try {
225 return channel.fd().isTcpCork();
226 } catch (IOException e) {
227 throw new ChannelException(e);
228 }
229 }
230
231
232
233
234
235 public long getTcpNotSentLowAt() {
236 try {
237 return Native.getTcpNotSentLowAt(channel.fd().intValue()) & MAX_UINT32_T;
238 } catch (IOException e) {
239 throw new ChannelException(e);
240 }
241 }
242
243
244
245
246 public int getTcpKeepIdle() {
247 try {
248 return Native.getTcpKeepIdle(channel.fd().intValue());
249 } catch (IOException e) {
250 throw new ChannelException(e);
251 }
252 }
253
254
255
256
257 public int getTcpKeepIntvl() {
258 try {
259 return Native.getTcpKeepIntvl(channel.fd().intValue());
260 } catch (IOException e) {
261 throw new ChannelException(e);
262 }
263 }
264
265
266
267
268 public int getTcpKeepCnt() {
269 try {
270 return Native.getTcpKeepCnt(channel.fd().intValue());
271 } catch (IOException e) {
272 throw new ChannelException(e);
273 }
274 }
275
276
277
278
279 public int getTcpUserTimeout() {
280 try {
281 return Native.getTcpUserTimeout(channel.fd().intValue());
282 } catch (IOException e) {
283 throw new ChannelException(e);
284 }
285 }
286
287 @Override
288 public EpollSocketChannelConfig setKeepAlive(boolean keepAlive) {
289 try {
290 channel.fd().setKeepAlive(keepAlive);
291 return this;
292 } catch (IOException e) {
293 throw new ChannelException(e);
294 }
295 }
296
297 @Override
298 public EpollSocketChannelConfig setPerformancePreferences(
299 int connectionTime, int latency, int bandwidth) {
300 return this;
301 }
302
303 @Override
304 public EpollSocketChannelConfig setReceiveBufferSize(int receiveBufferSize) {
305 try {
306 channel.fd().setReceiveBufferSize(receiveBufferSize);
307 return this;
308 } catch (IOException e) {
309 throw new ChannelException(e);
310 }
311 }
312
313 @Override
314 public EpollSocketChannelConfig setReuseAddress(boolean reuseAddress) {
315 try {
316 Native.setReuseAddress(channel.fd().intValue(), reuseAddress ? 1 : 0);
317 return this;
318 } catch (IOException e) {
319 throw new ChannelException(e);
320 }
321 }
322
323 @Override
324 public EpollSocketChannelConfig setSendBufferSize(int sendBufferSize) {
325 try {
326 channel.fd().setSendBufferSize(sendBufferSize);
327 return this;
328 } catch (IOException e) {
329 throw new ChannelException(e);
330 }
331 }
332
333 @Override
334 public EpollSocketChannelConfig setSoLinger(int soLinger) {
335 try {
336 channel.fd().setSoLinger(soLinger);
337 return this;
338 } catch (IOException e) {
339 throw new ChannelException(e);
340 }
341 }
342
343 @Override
344 public EpollSocketChannelConfig setTcpNoDelay(boolean tcpNoDelay) {
345 try {
346 channel.fd().setTcpNoDelay(tcpNoDelay);
347 return this;
348 } catch (IOException e) {
349 throw new ChannelException(e);
350 }
351 }
352
353
354
355
356 public EpollSocketChannelConfig setTcpCork(boolean tcpCork) {
357 try {
358 channel.fd().setTcpCork(tcpCork);
359 return this;
360 } catch (IOException e) {
361 throw new ChannelException(e);
362 }
363 }
364
365
366
367
368
369 public EpollSocketChannelConfig setTcpNotSentLowAt(long tcpNotSentLowAt) {
370 if (tcpNotSentLowAt < 0 || tcpNotSentLowAt > MAX_UINT32_T) {
371 throw new IllegalArgumentException("tcpNotSentLowAt must be a uint32_t");
372 }
373 try {
374 Native.setTcpNotSentLowAt(channel.fd().intValue(), (int) tcpNotSentLowAt);
375 return this;
376 } catch (IOException e) {
377 throw new ChannelException(e);
378 }
379 }
380
381 @Override
382 public EpollSocketChannelConfig setTrafficClass(int trafficClass) {
383 try {
384 Native.setTrafficClass(channel.fd().intValue(), trafficClass);
385 return this;
386 } catch (IOException e) {
387 throw new ChannelException(e);
388 }
389 }
390
391
392
393
394 public EpollSocketChannelConfig setTcpKeepIdle(int seconds) {
395 try {
396 Native.setTcpKeepIdle(channel.fd().intValue(), seconds);
397 return this;
398 } catch (IOException e) {
399 throw new ChannelException(e);
400 }
401 }
402
403
404
405
406 public EpollSocketChannelConfig setTcpKeepIntvl(int seconds) {
407 try {
408 Native.setTcpKeepIntvl(channel.fd().intValue(), seconds);
409 return this;
410 } catch (IOException e) {
411 throw new ChannelException(e);
412 }
413 }
414
415
416
417
418 @Deprecated
419 public EpollSocketChannelConfig setTcpKeepCntl(int probes) {
420 return setTcpKeepCnt(probes);
421 }
422
423
424
425
426 public EpollSocketChannelConfig setTcpKeepCnt(int probes) {
427 try {
428 Native.setTcpKeepCnt(channel.fd().intValue(), probes);
429 return this;
430 } catch (IOException e) {
431 throw new ChannelException(e);
432 }
433 }
434
435
436
437
438 public EpollSocketChannelConfig setTcpUserTimeout(int milliseconds) {
439 try {
440 Native.setTcpUserTimeout(channel.fd().intValue(), milliseconds);
441 return this;
442 } catch (IOException e) {
443 throw new ChannelException(e);
444 }
445 }
446
447
448
449
450
451
452 public EpollSocketChannelConfig setTcpMd5Sig(Map<InetAddress, byte[]> keys) {
453 try {
454 channel.setTcpMd5Sig(keys);
455 return this;
456 } catch (IOException e) {
457 throw new ChannelException(e);
458 }
459 }
460
461
462
463
464
465 public EpollSocketChannelConfig setTcpQuickAck(boolean quickAck) {
466 try {
467 channel.fd().setTcpQuickAck(quickAck);
468 return this;
469 } catch (IOException e) {
470 throw new ChannelException(e);
471 }
472 }
473
474
475
476
477
478 public boolean isTcpQuickAck() {
479 try {
480 return channel.fd().isTcpQuickAck();
481 } catch (IOException e) {
482 throw new ChannelException(e);
483 }
484 }
485
486 @Override
487 public boolean isAllowHalfClosure() {
488 return allowHalfClosure;
489 }
490
491 @Override
492 public EpollSocketChannelConfig setAllowHalfClosure(boolean allowHalfClosure) {
493 this.allowHalfClosure = allowHalfClosure;
494 return this;
495 }
496
497 @Override
498 public EpollSocketChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) {
499 super.setConnectTimeoutMillis(connectTimeoutMillis);
500 return this;
501 }
502
503 @Override
504 public EpollSocketChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) {
505 super.setMaxMessagesPerRead(maxMessagesPerRead);
506 return this;
507 }
508
509 @Override
510 public EpollSocketChannelConfig setWriteSpinCount(int writeSpinCount) {
511 super.setWriteSpinCount(writeSpinCount);
512 return this;
513 }
514
515 @Override
516 public EpollSocketChannelConfig setAllocator(ByteBufAllocator allocator) {
517 super.setAllocator(allocator);
518 return this;
519 }
520
521 @Override
522 public EpollSocketChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) {
523 super.setRecvByteBufAllocator(allocator);
524 return this;
525 }
526
527 @Override
528 public EpollSocketChannelConfig setAutoRead(boolean autoRead) {
529 super.setAutoRead(autoRead);
530 return this;
531 }
532
533 @Override
534 public EpollSocketChannelConfig setAutoClose(boolean autoClose) {
535 super.setAutoClose(autoClose);
536 return this;
537 }
538
539 @Override
540 public EpollSocketChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) {
541 super.setWriteBufferHighWaterMark(writeBufferHighWaterMark);
542 return this;
543 }
544
545 @Override
546 public EpollSocketChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) {
547 super.setWriteBufferLowWaterMark(writeBufferLowWaterMark);
548 return this;
549 }
550
551 @Override
552 public EpollSocketChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) {
553 super.setMessageSizeEstimator(estimator);
554 return this;
555 }
556
557 @Override
558 public EpollSocketChannelConfig setEpollMode(EpollMode mode) {
559 super.setEpollMode(mode);
560 return this;
561 }
562 }