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.ByteBuf;
19 import io.netty.channel.Channel;
20 import io.netty.channel.ChannelException;
21 import io.netty.channel.ChannelOutboundBuffer;
22 import io.netty.channel.socket.InternetProtocolFamily;
23 import io.netty.channel.socket.ServerSocketChannel;
24 import io.netty.channel.socket.SocketChannel;
25 import io.netty.channel.socket.SocketProtocolFamily;
26 import io.netty.util.concurrent.GlobalEventExecutor;
27
28 import java.io.IOException;
29 import java.net.InetAddress;
30 import java.net.InetSocketAddress;
31 import java.net.SocketAddress;
32 import java.util.Collection;
33 import java.util.Collections;
34 import java.util.Map;
35 import java.util.concurrent.Executor;
36
37 import static io.netty.channel.epoll.LinuxSocket.newSocketStream;
38 import static io.netty.channel.epoll.Native.IS_SUPPORTING_TCP_FASTOPEN_CLIENT;
39
40
41
42
43 public final class EpollSocketChannel extends AbstractEpollStreamChannel implements SocketChannel {
44
45 private final EpollSocketChannelConfig config;
46
47 private volatile Collection<InetAddress> tcpMd5SigAddresses = Collections.emptyList();
48
49 public EpollSocketChannel() {
50 super(newSocketStream(), false);
51 config = new EpollSocketChannelConfig(this);
52 }
53
54
55
56
57
58 @Deprecated
59 public EpollSocketChannel(InternetProtocolFamily protocol) {
60 super(newSocketStream(protocol), false);
61 config = new EpollSocketChannelConfig(this);
62 }
63
64 public EpollSocketChannel(SocketProtocolFamily protocol) {
65 super(newSocketStream(protocol), false);
66 config = new EpollSocketChannelConfig(this);
67 }
68
69 public EpollSocketChannel(int fd) {
70 super(fd);
71 config = new EpollSocketChannelConfig(this);
72 }
73
74 EpollSocketChannel(LinuxSocket fd, boolean active) {
75 super(fd, active);
76 config = new EpollSocketChannelConfig(this);
77 }
78
79 EpollSocketChannel(Channel parent, LinuxSocket fd, InetSocketAddress remoteAddress) {
80 super(parent, fd, remoteAddress);
81 config = new EpollSocketChannelConfig(this);
82
83 if (parent instanceof EpollServerSocketChannel) {
84 tcpMd5SigAddresses = ((EpollServerSocketChannel) parent).tcpMd5SigAddresses();
85 }
86 }
87
88
89
90
91
92 public EpollTcpInfo tcpInfo() {
93 return tcpInfo(new EpollTcpInfo());
94 }
95
96
97
98
99
100 public EpollTcpInfo tcpInfo(EpollTcpInfo info) {
101 try {
102 socket.getTcpInfo(info);
103 return info;
104 } catch (IOException e) {
105 throw new ChannelException(e);
106 }
107 }
108
109 @Override
110 public InetSocketAddress remoteAddress() {
111 return (InetSocketAddress) super.remoteAddress();
112 }
113
114 @Override
115 public InetSocketAddress localAddress() {
116 return (InetSocketAddress) super.localAddress();
117 }
118
119 @Override
120 public EpollSocketChannelConfig config() {
121 return config;
122 }
123
124 @Override
125 public ServerSocketChannel parent() {
126 return (ServerSocketChannel) super.parent();
127 }
128
129 @Override
130 protected AbstractEpollUnsafe newUnsafe() {
131 return new EpollSocketChannelUnsafe();
132 }
133
134 @Override
135 boolean doConnect0(SocketAddress remote) throws Exception {
136 if (IS_SUPPORTING_TCP_FASTOPEN_CLIENT && config.isTcpFastOpenConnect()) {
137 ChannelOutboundBuffer outbound = unsafe().outboundBuffer();
138 outbound.addFlush();
139 Object curr;
140 if ((curr = outbound.current()) instanceof ByteBuf) {
141 ByteBuf initialData = (ByteBuf) curr;
142
143
144 long localFlushedAmount = doWriteOrSendBytes(
145 initialData, (InetSocketAddress) remote, true);
146 if (localFlushedAmount > 0) {
147
148
149 outbound.removeBytes(localFlushedAmount);
150 return true;
151 }
152 }
153 }
154 return super.doConnect0(remote);
155 }
156
157 private final class EpollSocketChannelUnsafe extends EpollStreamUnsafe {
158 @Override
159 protected Executor prepareToClose() {
160 try {
161
162
163 if (isOpen() && config().getSoLinger() > 0) {
164
165
166
167
168 registration().cancel();
169 return GlobalEventExecutor.INSTANCE;
170 }
171 } catch (Throwable ignore) {
172
173
174
175 }
176 return null;
177 }
178 }
179
180 void setTcpMd5Sig(Map<InetAddress, byte[]> keys) throws IOException {
181
182 synchronized (this) {
183 tcpMd5SigAddresses = TcpMd5Util.newTcpMd5Sigs(this, tcpMd5SigAddresses, keys);
184 }
185 }
186 }