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