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