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