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.ByteBuf;
19 import io.netty.channel.Channel;
20 import io.netty.channel.ChannelOutboundBuffer;
21 import io.netty.channel.socket.InternetProtocolFamily;
22 import io.netty.channel.socket.ServerSocketChannel;
23 import io.netty.channel.socket.SocketChannel;
24 import io.netty.channel.socket.SocketProtocolFamily;
25 import io.netty.channel.unix.IovArray;
26 import io.netty.util.concurrent.GlobalEventExecutor;
27
28 import java.net.InetSocketAddress;
29 import java.net.SocketAddress;
30 import java.util.concurrent.Executor;
31
32 public final class KQueueSocketChannel extends AbstractKQueueStreamChannel implements SocketChannel {
33 private final KQueueSocketChannelConfig config;
34
35 public KQueueSocketChannel() {
36 super(null, BsdSocket.newSocketStream(), false);
37 config = new KQueueSocketChannelConfig(this);
38 }
39
40
41
42
43 @Deprecated
44 public KQueueSocketChannel(InternetProtocolFamily protocol) {
45 super(null, BsdSocket.newSocketStream(protocol), false);
46 config = new KQueueSocketChannelConfig(this);
47 }
48
49 public KQueueSocketChannel(SocketProtocolFamily protocol) {
50 super(null, BsdSocket.newSocketStream(protocol), false);
51 config = new KQueueSocketChannelConfig(this);
52 }
53
54 public KQueueSocketChannel(int fd) {
55 super(new BsdSocket(fd));
56 config = new KQueueSocketChannelConfig(this);
57 }
58
59 KQueueSocketChannel(Channel parent, BsdSocket fd, InetSocketAddress remoteAddress) {
60 super(parent, fd, remoteAddress);
61 config = new KQueueSocketChannelConfig(this);
62 }
63
64 @Override
65 public InetSocketAddress remoteAddress() {
66 return (InetSocketAddress) super.remoteAddress();
67 }
68
69 @Override
70 public InetSocketAddress localAddress() {
71 return (InetSocketAddress) super.localAddress();
72 }
73
74 @Override
75 public KQueueSocketChannelConfig config() {
76 return config;
77 }
78
79 @Override
80 public ServerSocketChannel parent() {
81 return (ServerSocketChannel) super.parent();
82 }
83
84 @Override
85 protected boolean doConnect0(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception {
86 if (config.isTcpFastOpenConnect()) {
87 ChannelOutboundBuffer outbound = unsafe().outboundBuffer();
88 outbound.addFlush();
89 Object curr;
90 if ((curr = outbound.current()) instanceof ByteBuf) {
91 ByteBuf initialData = (ByteBuf) curr;
92
93 if (initialData.isReadable()) {
94 IovArray iov = new IovArray(config.getAllocator().directBuffer());
95 try {
96 iov.add(initialData, initialData.readerIndex(), initialData.readableBytes());
97 int bytesSent = socket.connectx(
98 (InetSocketAddress) localAddress, (InetSocketAddress) remoteAddress, iov, true);
99 writeFilter(true);
100 outbound.removeBytes(Math.abs(bytesSent));
101
102
103 return bytesSent > 0;
104 } finally {
105 iov.release();
106 }
107 }
108 }
109 }
110 return super.doConnect0(remoteAddress, localAddress);
111 }
112
113 @Override
114 protected AbstractKQueueUnsafe newUnsafe() {
115 return new KQueueSocketChannelUnsafe();
116 }
117
118 private final class KQueueSocketChannelUnsafe extends KQueueStreamUnsafe {
119 @Override
120 protected Executor prepareToClose() {
121 try {
122
123
124 if (isOpen() && config().getSoLinger() > 0) {
125
126
127
128
129 doDeregister();
130 return GlobalEventExecutor.INSTANCE;
131 }
132 } catch (Throwable ignore) {
133
134
135
136 }
137 return null;
138 }
139 }
140 }