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.channel.Channel;
19 import io.netty.channel.ChannelFuture;
20 import io.netty.channel.ChannelPromise;
21 import io.netty.channel.EventLoop;
22 import io.netty.channel.socket.ServerSocketChannel;
23 import io.netty.channel.socket.SocketChannel;
24 import io.netty.channel.unix.FileDescriptor;
25 import io.netty.util.concurrent.GlobalEventExecutor;
26 import io.netty.util.internal.OneTimeTask;
27
28 import java.net.InetSocketAddress;
29 import java.net.SocketAddress;
30 import java.util.concurrent.Executor;
31
32
33
34
35
36 public final class EpollSocketChannel extends AbstractEpollStreamChannel implements SocketChannel {
37
38 private final EpollSocketChannelConfig config;
39
40 private volatile InetSocketAddress local;
41 private volatile InetSocketAddress remote;
42
43 EpollSocketChannel(Channel parent, int fd, InetSocketAddress remote) {
44 super(parent, fd);
45 config = new EpollSocketChannelConfig(this);
46
47
48 this.remote = remote;
49 local = Native.localAddress(fd);
50 }
51
52 public EpollSocketChannel() {
53 super(Native.socketStreamFd());
54 config = new EpollSocketChannelConfig(this);
55 }
56
57
58
59
60 public EpollSocketChannel(FileDescriptor fd) {
61 super(fd);
62 config = new EpollSocketChannelConfig(this);
63
64
65
66 remote = Native.remoteAddress(fd.intValue());
67 local = Native.localAddress(fd.intValue());
68 }
69
70
71
72
73 public EpollTcpInfo tcpInfo() {
74 return tcpInfo(new EpollTcpInfo());
75 }
76
77
78
79
80
81 public EpollTcpInfo tcpInfo(EpollTcpInfo info) {
82 Native.tcpInfo(fd().intValue(), info);
83 return info;
84 }
85
86 @Override
87 public InetSocketAddress remoteAddress() {
88 return (InetSocketAddress) super.remoteAddress();
89 }
90
91 @Override
92 public InetSocketAddress localAddress() {
93 return (InetSocketAddress) super.localAddress();
94 }
95
96 @Override
97 protected SocketAddress localAddress0() {
98 return local;
99 }
100
101 @Override
102 protected SocketAddress remoteAddress0() {
103 if (remote == null) {
104
105 InetSocketAddress address = Native.remoteAddress(fd().intValue());
106 if (address != null) {
107 remote = address;
108 }
109 return address;
110 }
111 return remote;
112 }
113
114 @Override
115 protected void doBind(SocketAddress local) throws Exception {
116 InetSocketAddress localAddress = (InetSocketAddress) local;
117 int fd = fd().intValue();
118 Native.bind(fd, localAddress);
119 this.local = Native.localAddress(fd);
120 }
121
122 @Override
123 public EpollSocketChannelConfig config() {
124 return config;
125 }
126
127 @Override
128 public boolean isInputShutdown() {
129 return isInputShutdown0();
130 }
131
132 @Override
133 public boolean isOutputShutdown() {
134 return isOutputShutdown0();
135 }
136
137 @Override
138 public ChannelFuture shutdownOutput() {
139 return shutdownOutput(newPromise());
140 }
141
142 @Override
143 public ChannelFuture shutdownOutput(final ChannelPromise promise) {
144 Executor closeExecutor = ((EpollSocketChannelUnsafe) unsafe()).closeExecutor();
145 if (closeExecutor != null) {
146 closeExecutor.execute(new OneTimeTask() {
147 @Override
148 public void run() {
149 shutdownOutput0(promise);
150 }
151 });
152 } else {
153 EventLoop loop = eventLoop();
154 if (loop.inEventLoop()) {
155 shutdownOutput0(promise);
156 } else {
157 loop.execute(new OneTimeTask() {
158 @Override
159 public void run() {
160 shutdownOutput0(promise);
161 }
162 });
163 }
164 }
165 return promise;
166 }
167
168 @Override
169 public ServerSocketChannel parent() {
170 return (ServerSocketChannel) super.parent();
171 }
172
173 @Override
174 protected AbstractEpollUnsafe newUnsafe() {
175 return new EpollSocketChannelUnsafe();
176 }
177
178 @Override
179 protected boolean doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception {
180 if (localAddress != null) {
181 checkResolvable((InetSocketAddress) localAddress);
182 }
183 checkResolvable((InetSocketAddress) remoteAddress);
184 if (super.doConnect(remoteAddress, localAddress)) {
185 int fd = fd().intValue();
186 local = Native.localAddress(fd);
187 remote = (InetSocketAddress) remoteAddress;
188 return true;
189 }
190 return false;
191 }
192
193 private final class EpollSocketChannelUnsafe extends EpollStreamUnsafe {
194 @Override
195 protected Executor closeExecutor() {
196 if (config().getSoLinger() > 0) {
197 return GlobalEventExecutor.INSTANCE;
198 }
199 return null;
200 }
201 }
202 }