1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.newsclub.net.unix;
19
20 import static java.util.Objects.requireNonNull;
21
22 import java.io.FileDescriptor;
23 import java.io.IOException;
24 import java.net.ProtocolFamily;
25 import java.net.ServerSocket;
26 import java.net.SocketAddress;
27 import java.net.SocketOption;
28 import java.net.StandardProtocolFamily;
29 import java.nio.channels.ServerSocketChannel;
30 import java.nio.channels.spi.SelectorProvider;
31 import java.util.Objects;
32 import java.util.Set;
33
34 import org.eclipse.jdt.annotation.NonNull;
35 import org.eclipse.jdt.annotation.Nullable;
36
37 import com.kohlschutter.annotations.compiletime.SuppressFBWarnings;
38
39
40
41
42
43
44
45 public abstract class AFServerSocketChannel<A extends AFSocketAddress> extends ServerSocketChannel
46 implements FileDescriptorAccess, AFSomeSocketChannel {
47 private final @NonNull AFServerSocket<A> afSocket;
48
49
50
51
52
53
54
55 @SuppressWarnings("all")
56 @SuppressFBWarnings("CT_CONSTRUCTOR_THROW")
57 protected AFServerSocketChannel(AFServerSocket<A> socket, AFSelectorProvider<A> sp) {
58 super(sp);
59 this.afSocket = Objects.requireNonNull(socket);
60 }
61
62
63
64 @SuppressWarnings("unchecked")
65 @Override
66 public <T> T getOption(SocketOption<T> name) throws IOException {
67 if (name instanceof AFSocketOption<?>) {
68 return getAFCore().getOption((AFSocketOption<T>) name);
69 }
70 Integer optionId = SocketOptionsMapper.resolve(name);
71 if (optionId == null) {
72 throw new UnsupportedOperationException("unsupported option");
73 } else {
74 return (T) afSocket.getAFImpl().getOption(optionId);
75 }
76 }
77
78 @Override
79 public <T> AFServerSocketChannel<A> setOption(SocketOption<T> name, T value) throws IOException {
80 if (name instanceof AFSocketOption<?>) {
81 getAFCore().setOption((AFSocketOption<T>) name, value);
82 return this;
83 }
84 Integer optionId = SocketOptionsMapper.resolve(name);
85 if (optionId == null) {
86 throw new UnsupportedOperationException("unsupported option");
87 } else {
88 afSocket.getAFImpl().setOption(optionId, value);
89 }
90 return this;
91 }
92
93 @Override
94 public final Set<SocketOption<?>> supportedOptions() {
95 return SocketOptionsMapper.SUPPORTED_SOCKET_OPTIONS;
96 }
97
98
99
100 @Override
101 public final AFServerSocketChannel<A> bind(SocketAddress local, int backlog) throws IOException {
102 afSocket.bind(local, backlog);
103 return this;
104 }
105
106 @SuppressFBWarnings("EI_EXPOSE_REP")
107 @Override
108 public final AFServerSocket<A> socket() {
109 return afSocket;
110 }
111
112 @Override
113 public AFSocketChannel<A> accept() throws IOException {
114 boolean complete = false;
115 Exception exception = null;
116 try {
117 begin();
118 AFSocket<A> socket = afSocket.accept1(false);
119 complete = true;
120 return socket == null ? null : socket.getChannel();
121 } catch (IOException e) {
122 throw InterruptibleChannelUtil.ioExceptionOrThrowRuntimeException(
123 (exception = InterruptibleChannelUtil.handleException(this, e)));
124 } finally {
125 InterruptibleChannelUtil.endInterruptable(this, this::end, complete, exception);
126 }
127 }
128
129 @Override
130 public final @Nullable A getLocalAddress() {
131 return getLocalSocketAddress();
132 }
133
134 @Override
135 public final @Nullable A getLocalSocketAddress() {
136 return afSocket.getLocalSocketAddress();
137 }
138
139
140
141
142
143
144
145
146
147 public final boolean isLocalSocketAddressValid() {
148 return afSocket.isLocalSocketAddressValid();
149 }
150
151 @Override
152 protected final void implCloseSelectableChannel() throws IOException {
153 afSocket.close();
154 }
155
156 @Override
157 protected final void implConfigureBlocking(boolean block) throws IOException {
158 getAFCore().implConfigureBlocking(block);
159 }
160
161 final AFSocketCore getAFCore() {
162 return afSocket.getAFImpl().getCore();
163 }
164
165 @Override
166 public final FileDescriptor getFileDescriptor() throws IOException {
167 return afSocket.getFileDescriptor();
168 }
169
170
171
172
173
174
175
176
177
178 public final boolean isDeleteOnClose() {
179 return socket().isDeleteOnClose();
180 }
181
182
183
184
185
186
187
188
189
190
191 public final void setDeleteOnClose(boolean b) {
192 socket().setDeleteOnClose(b);
193 }
194
195 @Override
196 public void setShutdownOnClose(boolean enabled) {
197 socket().setShutdownOnClose(enabled);
198 }
199
200
201
202
203
204
205
206
207
208
209
210
211
212 @SuppressFBWarnings("HSM_HIDING_METHOD")
213 public static ServerSocketChannel open(ProtocolFamily family) throws IOException {
214 requireNonNull(family);
215
216 if (family instanceof AFProtocolFamily) {
217 return ((AFProtocolFamily) family).openServerSocketChannel();
218 } else if ("UNIX".equals(family.name())) {
219 return AFUNIXServerSocketChannel.open();
220 } else if (family instanceof StandardProtocolFamily) {
221 return ServerSocketChannel.open();
222 } else {
223 throw new UnsupportedOperationException("Protocol family not supported");
224 }
225 }
226 }