163 * or more generally, when there is no receive queue to identify.
164 * The socket option is supported by both stream-oriented and datagram-oriented
165 * sockets.
166 *
167 * <p> The socket option is read-only and an attempt to set the socket option
168 * will throw {@code SocketException}.
169 *
170 * @apiNote
171 * Network devices may have multiple queues or channels to transmit and receive
172 * network packets. The {@code SO_INCOMING_NAPI_ID} socket option provides a hint
173 * to the application to indicate the receive queue on which an incoming socket
174 * connection or packets for that connection are directed to. An application may
175 * take advantage of this by handling all socket connections assigned to a
176 * specific queue on one thread.
177 *
178 * @since 15
179 */
180 public static final SocketOption<Integer> SO_INCOMING_NAPI_ID
181 = new ExtSocketOption<Integer>("SO_INCOMING_NAPI_ID", Integer.class);
182
183 private static final PlatformSocketOptions platformSocketOptions =
184 PlatformSocketOptions.get();
185
186 private static final boolean quickAckSupported =
187 platformSocketOptions.quickAckSupported();
188 private static final boolean keepAliveOptSupported =
189 platformSocketOptions.keepAliveOptionsSupported();
190 private static final boolean incomingNapiIdOptSupported =
191 platformSocketOptions.incomingNapiIdSupported();
192 private static final Set<SocketOption<?>> extendedOptions = options();
193
194 static Set<SocketOption<?>> options() {
195 Set<SocketOption<?>> options = new HashSet<>();
196 if (quickAckSupported) {
197 options.add(TCP_QUICKACK);
198 }
199 if (incomingNapiIdOptSupported) {
200 options.add(SO_INCOMING_NAPI_ID);
201 }
202 if (keepAliveOptSupported) {
203 options.addAll(Set.of(TCP_KEEPCOUNT, TCP_KEEPIDLE, TCP_KEEPINTERVAL));
204 }
205 return Collections.unmodifiableSet(options);
206 }
207
208 static {
209 // Registers the extended socket options with the base module.
210 sun.net.ext.ExtendedSocketOptions.register(
211 new sun.net.ext.ExtendedSocketOptions(extendedOptions) {
212
213 @Override
214 @SuppressWarnings("removal")
215 public void setOption(FileDescriptor fd,
216 SocketOption<?> option,
217 Object value)
218 throws SocketException
219 {
220 if (fd == null || !fd.valid())
221 throw new SocketException("socket closed");
222
223 if (option == TCP_QUICKACK) {
224 setQuickAckOption(fd, (boolean) value);
225 } else if (option == TCP_KEEPCOUNT) {
226 setTcpkeepAliveProbes(fd, (Integer) value);
227 } else if (option == TCP_KEEPIDLE) {
228 setTcpKeepAliveTime(fd, (Integer) value);
229 } else if (option == TCP_KEEPINTERVAL) {
230 setTcpKeepAliveIntvl(fd, (Integer) value);
231 } else if (option == SO_INCOMING_NAPI_ID) {
232 if (!incomingNapiIdOptSupported)
233 throw new UnsupportedOperationException("Attempt to set unsupported option " + option);
234 else
235 throw new SocketException("Attempt to set read only option " + option);
236 } else {
237 throw new InternalError("Unexpected option " + option);
238 }
239 }
240
241 @Override
242 @SuppressWarnings("removal")
243 public Object getOption(FileDescriptor fd,
244 SocketOption<?> option)
245 throws SocketException
246 {
247 if (fd == null || !fd.valid())
248 throw new SocketException("socket closed");
249
250 if (option == TCP_QUICKACK) {
251 return getQuickAckOption(fd);
252 } else if (option == TCP_KEEPCOUNT) {
253 return getTcpkeepAliveProbes(fd);
254 } else if (option == TCP_KEEPIDLE) {
255 return getTcpKeepAliveTime(fd);
256 } else if (option == TCP_KEEPINTERVAL) {
257 return getTcpKeepAliveIntvl(fd);
258 } else if (option == SO_INCOMING_NAPI_ID) {
259 return getIncomingNapiId(fd);
260 } else {
261 throw new InternalError("Unexpected option " + option);
262 }
263 }
264 });
265 }
266
267 private static final JavaIOFileDescriptorAccess fdAccess =
268 SharedSecrets.getJavaIOFileDescriptorAccess();
269
270 private static void setQuickAckOption(FileDescriptor fd, boolean enable)
271 throws SocketException {
272 platformSocketOptions.setQuickAck(fdAccess.get(fd), enable);
273 }
274
275 private static Object getQuickAckOption(FileDescriptor fd)
276 throws SocketException {
277 return platformSocketOptions.getQuickAck(fdAccess.get(fd));
278 }
279
280 private static void setTcpkeepAliveProbes(FileDescriptor fd, int value)
281 throws SocketException {
282 platformSocketOptions.setTcpkeepAliveProbes(fdAccess.get(fd), value);
283 }
284
285 private static void setTcpKeepAliveTime(FileDescriptor fd, int value)
286 throws SocketException {
287 platformSocketOptions.setTcpKeepAliveTime(fdAccess.get(fd), value);
288 }
289
290 private static void setTcpKeepAliveIntvl(FileDescriptor fd, int value)
291 throws SocketException {
292 platformSocketOptions.setTcpKeepAliveIntvl(fdAccess.get(fd), value);
293 }
294
328 new PrivilegedAction<String>() {
329 public String run() {
330 return System.getProperty("os.name");
331 }
332 });
333 if ("Linux".equals(osname)) {
334 return newInstance("jdk.net.LinuxSocketOptions");
335 } else if (osname.startsWith("Mac")) {
336 return newInstance("jdk.net.MacOSXSocketOptions");
337 } else {
338 return new PlatformSocketOptions();
339 }
340 }
341
342 private static final PlatformSocketOptions instance = create();
343
344 static PlatformSocketOptions get() {
345 return instance;
346 }
347
348 void setQuickAck(int fd, boolean on) throws SocketException {
349 throw new UnsupportedOperationException("unsupported TCP_QUICKACK option");
350 }
351
352 boolean getQuickAck(int fd) throws SocketException {
353 throw new UnsupportedOperationException("unsupported TCP_QUICKACK option");
354 }
355
356 boolean quickAckSupported() {
357 return false;
358 }
359
360 boolean keepAliveOptionsSupported() {
361 return false;
362 }
363
364 void setTcpkeepAliveProbes(int fd, final int value) throws SocketException {
365 throw new UnsupportedOperationException("unsupported TCP_KEEPCNT option");
366 }
367
368 void setTcpKeepAliveTime(int fd, final int value) throws SocketException {
369 throw new UnsupportedOperationException("unsupported TCP_KEEPIDLE option");
370 }
371
372 void setTcpKeepAliveIntvl(int fd, final int value) throws SocketException {
373 throw new UnsupportedOperationException("unsupported TCP_KEEPINTVL option");
374 }
375
376 int getTcpkeepAliveProbes(int fd) throws SocketException {
377 throw new UnsupportedOperationException("unsupported TCP_KEEPCNT option");
378 }
379
380 int getTcpKeepAliveTime(int fd) throws SocketException {
381 throw new UnsupportedOperationException("unsupported TCP_KEEPIDLE option");
382 }
383
384 int getTcpKeepAliveIntvl(int fd) throws SocketException {
385 throw new UnsupportedOperationException("unsupported TCP_KEEPINTVL option");
386 }
387
388 boolean incomingNapiIdSupported() {
389 return false;
390 }
391
|
163 * or more generally, when there is no receive queue to identify.
164 * The socket option is supported by both stream-oriented and datagram-oriented
165 * sockets.
166 *
167 * <p> The socket option is read-only and an attempt to set the socket option
168 * will throw {@code SocketException}.
169 *
170 * @apiNote
171 * Network devices may have multiple queues or channels to transmit and receive
172 * network packets. The {@code SO_INCOMING_NAPI_ID} socket option provides a hint
173 * to the application to indicate the receive queue on which an incoming socket
174 * connection or packets for that connection are directed to. An application may
175 * take advantage of this by handling all socket connections assigned to a
176 * specific queue on one thread.
177 *
178 * @since 15
179 */
180 public static final SocketOption<Integer> SO_INCOMING_NAPI_ID
181 = new ExtSocketOption<Integer>("SO_INCOMING_NAPI_ID", Integer.class);
182
183 /**
184 * Unix Domain peer credentials.
185 *
186 * <p> The value of this socket option is a {@link UnixDomainPrincipal} that
187 * represents the credentials of a peer connected to a Unix Domain socket.
188 * The credentials are those that applied at the time the socket was first
189 * connected or accepted.
190 *
191 * <p> The socket option is read-only and an attempt to set the socket option
192 * will throw {@code SocketException}. {@code SocketException} is also thrown
193 * when attempting to get the value of the socket option on an unconnected Unix
194 * Domain socket.
195 *
196 * @since 16
197 */
198 public static final SocketOption<UnixDomainPrincipal> SO_PEERCRED
199 = new ExtSocketOption<UnixDomainPrincipal>
200 ("SO_PEERCRED", UnixDomainPrincipal.class);
201
202 private static final PlatformSocketOptions platformSocketOptions =
203 PlatformSocketOptions.get();
204
205 private static final boolean quickAckSupported =
206 platformSocketOptions.quickAckSupported();
207 private static final boolean keepAliveOptSupported =
208 platformSocketOptions.keepAliveOptionsSupported();
209 private static final boolean peerCredentialsSupported =
210 platformSocketOptions.peerCredentialsSupported();
211 private static final boolean incomingNapiIdOptSupported =
212 platformSocketOptions.incomingNapiIdSupported();
213 private static final Set<SocketOption<?>> extendedOptions = options();
214
215 static Set<SocketOption<?>> options() {
216 Set<SocketOption<?>> options = new HashSet<>();
217 if (quickAckSupported) {
218 options.add(TCP_QUICKACK);
219 }
220 if (incomingNapiIdOptSupported) {
221 options.add(SO_INCOMING_NAPI_ID);
222 }
223 if (keepAliveOptSupported) {
224 options.addAll(Set.of(TCP_KEEPCOUNT, TCP_KEEPIDLE, TCP_KEEPINTERVAL));
225 }
226 if (peerCredentialsSupported) {
227 options.add(SO_PEERCRED);
228 }
229 return Collections.unmodifiableSet(options);
230 }
231
232 static {
233 // Registers the extended socket options with the base module.
234 sun.net.ext.ExtendedSocketOptions.register(
235 new sun.net.ext.ExtendedSocketOptions(extendedOptions) {
236
237 @Override
238 @SuppressWarnings("removal")
239 public void setOption(FileDescriptor fd,
240 SocketOption<?> option,
241 Object value)
242 throws SocketException
243 {
244 if (fd == null || !fd.valid())
245 throw new SocketException("socket closed");
246
247 if (option == TCP_QUICKACK) {
248 setQuickAckOption(fd, (boolean) value);
249 } else if (option == TCP_KEEPCOUNT) {
250 setTcpkeepAliveProbes(fd, (Integer) value);
251 } else if (option == TCP_KEEPIDLE) {
252 setTcpKeepAliveTime(fd, (Integer) value);
253 } else if (option == TCP_KEEPINTERVAL) {
254 setTcpKeepAliveIntvl(fd, (Integer) value);
255 } else if (option == SO_INCOMING_NAPI_ID) {
256 if (!incomingNapiIdOptSupported)
257 throw new UnsupportedOperationException("Attempt to set unsupported option " + option);
258 else
259 throw new SocketException("Attempt to set read only option " + option);
260 } else if (option == SO_PEERCRED) {
261 throw new SocketException("SO_PEERCRED cannot be set ");
262 } else {
263 throw new InternalError("Unexpected option " + option);
264 }
265 }
266
267 @Override
268 @SuppressWarnings("removal")
269 public Object getOption(FileDescriptor fd,
270 SocketOption<?> option)
271 throws SocketException
272 {
273 if (fd == null || !fd.valid())
274 throw new SocketException("socket closed");
275
276 if (option == TCP_QUICKACK) {
277 return getQuickAckOption(fd);
278 } else if (option == TCP_KEEPCOUNT) {
279 return getTcpkeepAliveProbes(fd);
280 } else if (option == TCP_KEEPIDLE) {
281 return getTcpKeepAliveTime(fd);
282 } else if (option == TCP_KEEPINTERVAL) {
283 return getTcpKeepAliveIntvl(fd);
284 } else if (option == SO_PEERCRED) {
285 return getSoPeerCred(fd);
286 } else if (option == SO_INCOMING_NAPI_ID) {
287 return getIncomingNapiId(fd);
288 } else {
289 throw new InternalError("Unexpected option " + option);
290 }
291 }
292 });
293 }
294
295 private static final JavaIOFileDescriptorAccess fdAccess =
296 SharedSecrets.getJavaIOFileDescriptorAccess();
297
298 private static void setQuickAckOption(FileDescriptor fd, boolean enable)
299 throws SocketException {
300 platformSocketOptions.setQuickAck(fdAccess.get(fd), enable);
301 }
302
303 private static Object getSoPeerCred(FileDescriptor fd)
304 throws SocketException {
305 return platformSocketOptions.getSoPeerCred(fdAccess.get(fd));
306 }
307
308 private static Object getQuickAckOption(FileDescriptor fd)
309 throws SocketException {
310 return platformSocketOptions.getQuickAck(fdAccess.get(fd));
311 }
312
313 private static void setTcpkeepAliveProbes(FileDescriptor fd, int value)
314 throws SocketException {
315 platformSocketOptions.setTcpkeepAliveProbes(fdAccess.get(fd), value);
316 }
317
318 private static void setTcpKeepAliveTime(FileDescriptor fd, int value)
319 throws SocketException {
320 platformSocketOptions.setTcpKeepAliveTime(fdAccess.get(fd), value);
321 }
322
323 private static void setTcpKeepAliveIntvl(FileDescriptor fd, int value)
324 throws SocketException {
325 platformSocketOptions.setTcpKeepAliveIntvl(fdAccess.get(fd), value);
326 }
327
361 new PrivilegedAction<String>() {
362 public String run() {
363 return System.getProperty("os.name");
364 }
365 });
366 if ("Linux".equals(osname)) {
367 return newInstance("jdk.net.LinuxSocketOptions");
368 } else if (osname.startsWith("Mac")) {
369 return newInstance("jdk.net.MacOSXSocketOptions");
370 } else {
371 return new PlatformSocketOptions();
372 }
373 }
374
375 private static final PlatformSocketOptions instance = create();
376
377 static PlatformSocketOptions get() {
378 return instance;
379 }
380
381 boolean peerCredentialsSupported() {
382 return false;
383 }
384
385 void setQuickAck(int fd, boolean on) throws SocketException {
386 throw new UnsupportedOperationException("unsupported TCP_QUICKACK option");
387 }
388
389 boolean getQuickAck(int fd) throws SocketException {
390 throw new UnsupportedOperationException("unsupported TCP_QUICKACK option");
391 }
392
393 boolean quickAckSupported() {
394 return false;
395 }
396
397 boolean keepAliveOptionsSupported() {
398 return false;
399 }
400
401 void setTcpkeepAliveProbes(int fd, final int value) throws SocketException {
402 throw new UnsupportedOperationException("unsupported TCP_KEEPCNT option");
403 }
404
405 void setTcpKeepAliveTime(int fd, final int value) throws SocketException {
406 throw new UnsupportedOperationException("unsupported TCP_KEEPIDLE option");
407 }
408
409 UnixDomainPrincipal getSoPeerCred(int fd) throws SocketException {
410 throw new UnsupportedOperationException("unsupported SO_PEERCRED option");
411 }
412
413 void setTcpKeepAliveIntvl(int fd, final int value) throws SocketException {
414 throw new UnsupportedOperationException("unsupported TCP_KEEPINTVL option");
415 }
416
417 int getTcpkeepAliveProbes(int fd) throws SocketException {
418 throw new UnsupportedOperationException("unsupported TCP_KEEPCNT option");
419 }
420
421 int getTcpKeepAliveTime(int fd) throws SocketException {
422 throw new UnsupportedOperationException("unsupported TCP_KEEPIDLE option");
423 }
424
425 int getTcpKeepAliveIntvl(int fd) throws SocketException {
426 throw new UnsupportedOperationException("unsupported TCP_KEEPINTVL option");
427 }
428
429 boolean incomingNapiIdSupported() {
430 return false;
431 }
432
|