8297778: Modernize and improve module jdk.sctp

Reviewed-by: dfuchs, stsypanov
This commit is contained in:
Per Minborg 2022-12-09 09:46:50 +00:00 committed by Daniel Fuchs
parent 11aece21f4
commit cb766c5535
19 changed files with 260 additions and 339 deletions

View File

@ -36,7 +36,7 @@ package com.sun.nio.sctp;
*/
public enum HandlerResult {
/**
* Try to receieve another message or notification.
* Try to receive another message or notification.
*/
CONTINUE,

View File

@ -24,6 +24,8 @@
*/
package com.sun.nio.sctp;
import java.io.Serial;
/**
* Unchecked exception thrown when an attempt is made to invoke the
* {@code receive} method of {@link SctpChannel} or {@link SctpMultiChannel}
@ -32,6 +34,7 @@ package com.sun.nio.sctp;
* @since 1.7
*/
public class IllegalReceiveException extends IllegalStateException {
@Serial
private static final long serialVersionUID = 2296619040988576224L;
/**

View File

@ -24,6 +24,8 @@
*/
package com.sun.nio.sctp;
import java.io.Serial;
/**
* Unchecked exception thrown when an attempt is made to remove an
* address that is not bound to the channel, or remove an address from a
@ -32,6 +34,7 @@ package com.sun.nio.sctp;
* @since 1.7
*/
public class IllegalUnbindException extends IllegalStateException {
@Serial
private static final long serialVersionUID = -310540883995532224L;
/**

View File

@ -24,6 +24,8 @@
*/
package com.sun.nio.sctp;
import java.io.Serial;
/**
* Unchecked exception thrown when an attempt is made to send a
* message to an invalid stream.
@ -31,6 +33,7 @@ package com.sun.nio.sctp;
* @since 1.7
*/
public class InvalidStreamException extends IllegalArgumentException {
@Serial
private static final long serialVersionUID = -9172703378046665558L;
/**

View File

@ -34,23 +34,24 @@ import sun.nio.ch.sctp.SctpStdSocketOption;
*
* @since 1.7
*/
public class SctpStandardSocketOptions {
public final class SctpStandardSocketOptions {
private SctpStandardSocketOptions() {}
/**
* Enables or disables message fragmentation.
*
* <P> The value of this socket option is a {@code Boolean} that represents
* whether the option is enabled or disabled. If enabled no SCTP message
* fragmentation will be performed. Instead if a message being sent
* fragmentation will be performed. Instead, if a message being sent
* exceeds the current PMTU size, the message will NOT be sent and
* an error will be indicated to the user.
*
* <P> It is implementation specific whether or not this option is
* supported.
*/
public static final SctpSocketOption<Boolean> SCTP_DISABLE_FRAGMENTS = new
SctpStdSocketOption<Boolean>("SCTP_DISABLE_FRAGMENTS", Boolean.class,
sun.nio.ch.sctp.SctpStdSocketOption.SCTP_DISABLE_FRAGMENTS);
public static final SctpSocketOption<Boolean> SCTP_DISABLE_FRAGMENTS =
new SctpStdSocketOption<>("SCTP_DISABLE_FRAGMENTS",
Boolean.class,
SctpStdSocketOption.SCTP_DISABLE_FRAGMENTS);
/**
* Enables or disables explicit message completion.
@ -67,9 +68,10 @@ public class SctpStandardSocketOptions {
* option is disabled. It is implementation specific whether or not this
* option is supported.
*/
public static final SctpSocketOption<Boolean> SCTP_EXPLICIT_COMPLETE = new
SctpStdSocketOption<Boolean>("SCTP_EXPLICIT_COMPLETE", Boolean.class,
sun.nio.ch.sctp.SctpStdSocketOption.SCTP_EXPLICIT_COMPLETE);
public static final SctpSocketOption<Boolean> SCTP_EXPLICIT_COMPLETE =
new SctpStdSocketOption<>("SCTP_EXPLICIT_COMPLETE",
Boolean.class,
SctpStdSocketOption.SCTP_EXPLICIT_COMPLETE);
/**
* Fragmented interleave controls how the presentation of messages occur
@ -118,9 +120,9 @@ public class SctpStandardSocketOptions {
* supported.
*/
public static final SctpSocketOption<Integer> SCTP_FRAGMENT_INTERLEAVE =
new SctpStdSocketOption<Integer>("SCTP_FRAGMENT_INTERLEAVE",
new SctpStdSocketOption<>("SCTP_FRAGMENT_INTERLEAVE",
Integer.class,
sun.nio.ch.sctp.SctpStdSocketOption.SCTP_FRAGMENT_INTERLEAVE);
SctpStdSocketOption.SCTP_FRAGMENT_INTERLEAVE);
/**
* The maximum number of streams requested by the local endpoint during
@ -158,8 +160,8 @@ public class SctpStandardSocketOptions {
*/
public static final SctpSocketOption
<SctpStandardSocketOptions.InitMaxStreams> SCTP_INIT_MAXSTREAMS =
new SctpStdSocketOption<SctpStandardSocketOptions.InitMaxStreams>(
"SCTP_INIT_MAXSTREAMS", SctpStandardSocketOptions.InitMaxStreams.class);
new SctpStdSocketOption<>("SCTP_INIT_MAXSTREAMS",
SctpStandardSocketOptions.InitMaxStreams.class);
/**
* Enables or disables a Nagle-like algorithm.
@ -170,8 +172,9 @@ public class SctpStandardSocketOptions {
* improve network efficiency.
*/
public static final SctpSocketOption<Boolean> SCTP_NODELAY =
new SctpStdSocketOption<Boolean>("SCTP_NODELAY", Boolean.class,
sun.nio.ch.sctp.SctpStdSocketOption.SCTP_NODELAY);
new SctpStdSocketOption<>("SCTP_NODELAY",
Boolean.class,
SctpStdSocketOption.SCTP_NODELAY);
/**
* Requests that the local SCTP stack use the given peer address as
@ -191,8 +194,8 @@ public class SctpStandardSocketOptions {
* set or queried directly.
*/
public static final SctpSocketOption<SocketAddress> SCTP_PRIMARY_ADDR =
new SctpStdSocketOption<SocketAddress>
("SCTP_PRIMARY_ADDR", SocketAddress.class);
new SctpStdSocketOption<>("SCTP_PRIMARY_ADDR",
SocketAddress.class);
/**
* Requests that the peer mark the enclosed address as the association
@ -216,8 +219,8 @@ public class SctpStandardSocketOptions {
* option is supported.
*/
public static final SctpSocketOption<SocketAddress> SCTP_SET_PEER_PRIMARY_ADDR =
new SctpStdSocketOption<SocketAddress>
("SCTP_SET_PEER_PRIMARY_ADDR", SocketAddress.class);
new SctpStdSocketOption<>("SCTP_SET_PEER_PRIMARY_ADDR",
SocketAddress.class);
/**
* The size of the socket send buffer.
@ -245,8 +248,9 @@ public class SctpStandardSocketOptions {
* dependent.
*/
public static final SctpSocketOption<Integer> SO_SNDBUF =
new SctpStdSocketOption<Integer>("SO_SNDBUF", Integer.class,
sun.nio.ch.sctp.SctpStdSocketOption.SO_SNDBUF);
new SctpStdSocketOption<>("SO_SNDBUF",
Integer.class,
SctpStdSocketOption.SO_SNDBUF);
/**
* The size of the socket receive buffer.
@ -272,8 +276,9 @@ public class SctpStandardSocketOptions {
* dependent.
*/
public static final SctpSocketOption<Integer> SO_RCVBUF =
new SctpStdSocketOption<Integer>("SO_RCVBUF", Integer.class,
sun.nio.ch.sctp.SctpStdSocketOption.SO_RCVBUF);
new SctpStdSocketOption<>("SO_RCVBUF",
Integer.class,
SctpStdSocketOption.SO_RCVBUF);
/**
* Linger on close if data is present.
@ -303,8 +308,9 @@ public class SctpStandardSocketOptions {
* its maximum value.
*/
public static final SctpSocketOption<Integer> SO_LINGER =
new SctpStdSocketOption<Integer>("SO_LINGER", Integer.class,
sun.nio.ch.sctp.SctpStdSocketOption.SO_LINGER);
new SctpStdSocketOption<>("SO_LINGER",
Integer.class,
SctpStdSocketOption.SO_LINGER);
/**
* This class is used to set the maximum number of inbound/outbound streams
@ -316,8 +322,8 @@ public class SctpStandardSocketOptions {
* @since 1.7
*/
public static class InitMaxStreams {
private int maxInStreams;
private int maxOutStreams;
private final int maxInStreams;
private final int maxOutStreams;
private InitMaxStreams(int maxInStreams, int maxOutStreams) {
this.maxInStreams = maxInStreams;
@ -378,11 +384,9 @@ public class SctpStandardSocketOptions {
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(super.toString()).append(" [");
sb.append("maxInStreams:").append(maxInStreams);
sb.append("maxOutStreams:").append(maxOutStreams).append("]");
return sb.toString();
return super.toString() + " [" +
"maxInStreams:" + maxInStreams +
"maxOutStreams:" + maxOutStreams + "]";
}
/**
@ -398,11 +402,9 @@ public class SctpStandardSocketOptions {
*/
@Override
public boolean equals(Object obj) {
if (obj != null && obj instanceof InitMaxStreams) {
InitMaxStreams that = (InitMaxStreams) obj;
if (this.maxInStreams == that.maxInStreams &&
this.maxOutStreams == that.maxOutStreams)
return true;
if (obj instanceof InitMaxStreams that) {
return this.maxInStreams == that.maxInStreams &&
this.maxOutStreams == that.maxOutStreams;
}
return false;
}

View File

@ -31,7 +31,7 @@ import java.net.SocketAddress;
* Notification emitted when a send failed notification has been received.
*
* <P> A send failed notification indicates that a message cannot be delivered.
* Typically this is because the association has been shutdown with unsent data
* Typically, this is because the association has been shutdown with unsent data
* in the socket output buffer, or in the case of a {@link SctpMultiChannel}
* the association failed to setup.
*
@ -81,7 +81,7 @@ public abstract class SendFailedNotification implements Notification {
public abstract int errorCode();
/**
* Returns the stream number that the messge was to be sent on.
* Returns the stream number that the message was to be sent on.
*
* @return The stream number
*/

View File

@ -156,15 +156,13 @@ public class MessageInfoImpl extends MessageInfo {
@Override
public String toString() {
StringBuilder sb = new StringBuilder(super.toString());
sb.append( "[Address: ").append(address)
.append(", Association: ").append(association)
.append(", Assoc ID: ").append(assocId)
.append(", Bytes: ").append(bytes)
.append(", Stream Number: ").append(streamNumber)
.append(", Complete: ").append(complete)
.append(", isUnordered: ").append(unordered)
.append("]");
return sb.toString();
return super.toString() + "[Address: " + address +
", Association: " + association +
", Assoc ID: " + assocId +
", Bytes: " + bytes +
", Stream Number: " + streamNumber +
", Complete: " + complete +
", isUnordered: " + unordered +
"]";
}
}

View File

@ -27,7 +27,7 @@ package sun.nio.ch.sctp;
import com.sun.nio.sctp.SctpSocketOption;
import java.lang.annotation.Native;
public class SctpStdSocketOption<T>
public final class SctpStdSocketOption<T>
implements SctpSocketOption<T>
{
/* for native mapping of int options */
@ -43,11 +43,10 @@ public class SctpStdSocketOption<T>
private final Class<T> type;
/* for native mapping of int options */
private int constValue;
private final int constValue;
public SctpStdSocketOption(String name, Class<T> type) {
this.name = name;
this.type = type;
this(name, type, 0);
}
public SctpStdSocketOption(String name, Class<T> type, int constValue) {

View File

@ -43,38 +43,27 @@ public class AssociationChange extends AssociationChangeNotification
private Association association;
/* assocId is used to lookup the association before the notification is
/* assocId is used to look up the association before the notification is
* returned to user code */
private int assocId;
private AssocChangeEvent event;
private int maxOutStreams;
private int maxInStreams;
private final int assocId;
private final AssocChangeEvent event;
private final int maxOutStreams;
private final int maxInStreams;
/* Invoked from native */
private AssociationChange(int assocId,
int intEvent,
int maxOutStreams,
int maxInStreams) {
switch (intEvent) {
case SCTP_COMM_UP :
this.event = AssocChangeEvent.COMM_UP;
break;
case SCTP_COMM_LOST :
this.event = AssocChangeEvent.COMM_LOST;
break;
case SCTP_RESTART :
this.event = AssocChangeEvent.RESTART;
break;
case SCTP_SHUTDOWN :
this.event = AssocChangeEvent.SHUTDOWN;
break;
case SCTP_CANT_START :
this.event = AssocChangeEvent.CANT_START;
break;
default :
throw new AssertionError(
this.event = switch (intEvent) {
case SCTP_COMM_UP -> AssocChangeEvent.COMM_UP;
case SCTP_COMM_LOST -> AssocChangeEvent.COMM_LOST;
case SCTP_RESTART -> AssocChangeEvent.RESTART;
case SCTP_SHUTDOWN -> AssocChangeEvent.SHUTDOWN;
case SCTP_CANT_START -> AssocChangeEvent.CANT_START;
default -> throw new AssertionError(
"Unknown Association Change Event type: " + intEvent);
}
};
this.assocId = assocId;
this.maxOutStreams = maxOutStreams;
@ -112,10 +101,8 @@ public class AssociationChange extends AssociationChangeNotification
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(super.toString()).append(" [");
sb.append("Association:").append(association);
sb.append(", Event: ").append(event).append("]");
return sb.toString();
return super.toString() + " [" +
"Association:" + association +
", Event: " + event + "]";
}
}

View File

@ -38,15 +38,13 @@ public class AssociationImpl extends Association {
@Override
public String toString() {
StringBuffer sb = new StringBuffer(super.toString());
return sb.append("[associationID:")
.append(associationID())
.append(", maxIn:")
.append(maxInboundStreams())
.append(", maxOut:")
.append(maxOutboundStreams())
.append("]")
.toString();
return super.toString() + "[associationID:" +
associationID() +
", maxIn:" +
maxInboundStreams() +
", maxOut:" +
maxOutboundStreams() +
"]";
}
}

View File

@ -45,36 +45,23 @@ public class PeerAddrChange extends PeerAddressChangeNotification
private Association association;
/* assocId is used to lookup the association before the notification is
/* assocId is used to look up the association before the notification is
* returned to user code */
private int assocId;
private SocketAddress address;
private AddressChangeEvent event;
private final int assocId;
private final SocketAddress address;
private final AddressChangeEvent event;
/* Invoked from native */
private PeerAddrChange(int assocId, SocketAddress address, int intEvent) {
switch (intEvent) {
case SCTP_ADDR_AVAILABLE :
this.event = AddressChangeEvent.ADDR_AVAILABLE;
break;
case SCTP_ADDR_UNREACHABLE :
this.event = AddressChangeEvent.ADDR_UNREACHABLE;
break;
case SCTP_ADDR_REMOVED :
this.event = AddressChangeEvent.ADDR_REMOVED;
break;
case SCTP_ADDR_ADDED :
this.event = AddressChangeEvent.ADDR_ADDED;
break;
case SCTP_ADDR_MADE_PRIM :
this.event = AddressChangeEvent.ADDR_MADE_PRIMARY;
break;
case SCTP_ADDR_CONFIRMED :
this.event = AddressChangeEvent.ADDR_CONFIRMED;
break;
default:
throw new AssertionError("Unknown event type");
}
this.event = switch (intEvent) {
case SCTP_ADDR_AVAILABLE -> AddressChangeEvent.ADDR_AVAILABLE;
case SCTP_ADDR_UNREACHABLE -> AddressChangeEvent.ADDR_UNREACHABLE;
case SCTP_ADDR_REMOVED -> AddressChangeEvent.ADDR_REMOVED;
case SCTP_ADDR_ADDED -> AddressChangeEvent.ADDR_ADDED;
case SCTP_ADDR_MADE_PRIM -> AddressChangeEvent.ADDR_MADE_PRIMARY;
case SCTP_ADDR_CONFIRMED -> AddressChangeEvent.ADDR_CONFIRMED;
default -> throw new AssertionError("Unknown event type");
};
this.assocId = assocId;
this.address = address;
}
@ -103,18 +90,15 @@ public class PeerAddrChange extends PeerAddressChangeNotification
@Override
public AddressChangeEvent event() {
assert event != null;
return event;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(super.toString()).append(" [");
sb.append("Address: ").append(address);
sb.append(", Association:").append(association);
sb.append(", Event: ").append(event).append("]");
return sb.toString();
return super.toString() + " [" +
"Address: " + address +
", Association:" + association +
", Event: " + event + "]";
}
}

View File

@ -51,7 +51,7 @@ public class ResultContainer {
}
boolean isNotification() {
return type() != MESSAGE && type() != NOTHING ? true : false;
return type() != MESSAGE && type() != NOTHING;
}
void clear() {
@ -68,8 +68,8 @@ public class ResultContainer {
MessageInfoImpl getMessageInfo() {
assert type() == MESSAGE;
if (value instanceof MessageInfoImpl)
return (MessageInfoImpl) value;
if (value instanceof MessageInfoImpl messageInfo)
return messageInfo;
return null;
}
@ -77,8 +77,8 @@ public class ResultContainer {
SendFailed getSendFailed() {
assert type() == SEND_FAILED;
if (value instanceof SendFailed)
return (SendFailed) value;
if (value instanceof SendFailed sendFailed)
return sendFailed;
return null;
}
@ -86,8 +86,8 @@ public class ResultContainer {
AssociationChange getAssociationChanged() {
assert type() == ASSOCIATION_CHANGED;
if (value instanceof AssociationChange)
return (AssociationChange) value;
if (value instanceof AssociationChange associationChanged)
return associationChanged;
return null;
}
@ -95,8 +95,8 @@ public class ResultContainer {
PeerAddrChange getPeerAddressChanged() {
assert type() == PEER_ADDRESS_CHANGED;
if (value instanceof PeerAddrChange)
return (PeerAddrChange) value;
if (value instanceof PeerAddrChange peerAddressChanged)
return peerAddressChanged;
return null;
}
@ -104,8 +104,8 @@ public class ResultContainer {
Shutdown getShutdown() {
assert type() == SHUTDOWN;
if (value instanceof Shutdown)
return (Shutdown) value;
if (value instanceof Shutdown shutdown)
return shutdown;
return null;
}
@ -115,13 +115,13 @@ public class ResultContainer {
StringBuilder sb = new StringBuilder();
sb.append("Type: ");
switch (type) {
case NOTHING: sb.append("NOTHING"); break;
case MESSAGE: sb.append("MESSAGE"); break;
case SEND_FAILED: sb.append("SEND FAILED"); break;
case ASSOCIATION_CHANGED: sb.append("ASSOCIATION CHANGE"); break;
case PEER_ADDRESS_CHANGED: sb.append("PEER ADDRESS CHANGE"); break;
case SHUTDOWN: sb.append("SHUTDOWN"); break;
default : sb.append("Unknown result type");
case NOTHING -> sb.append("NOTHING");
case MESSAGE -> sb.append("MESSAGE");
case SEND_FAILED -> sb.append("SEND FAILED");
case ASSOCIATION_CHANGED -> sb.append("ASSOCIATION CHANGE");
case PEER_ADDRESS_CHANGED -> sb.append("PEER ADDRESS CHANGE");
case SHUTDOWN -> sb.append("SHUTDOWN");
default -> sb.append("Unknown result type");
}
sb.append(", Value: ");
sb.append((value == null) ? "null" : value.toString());

View File

@ -30,6 +30,8 @@ import java.net.SocketException;
import java.net.InetSocketAddress;
import java.io.FileDescriptor;
import java.io.IOException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collections;
import java.util.Set;
import java.util.HashSet;
@ -83,9 +85,9 @@ public class SctpChannelImpl extends SctpChannel
private final int fdVal;
/* IDs of native threads doing send and receivess, for signalling */
private volatile long receiverThread = 0;
private volatile long senderThread = 0;
/* IDs of native threads doing send and receive, for signalling */
private volatile long receiverThread;
private volatile long senderThread;
/* Lock held by current receiving or connecting thread */
private final Object receiveLock = new Object();
@ -94,7 +96,7 @@ public class SctpChannelImpl extends SctpChannel
private final Object sendLock = new Object();
private final ThreadLocal<Boolean> receiveInvoked =
new ThreadLocal<Boolean>() {
new ThreadLocal<>() {
@Override protected Boolean initialValue() {
return Boolean.FALSE;
}
@ -113,11 +115,11 @@ public class SctpChannelImpl extends SctpChannel
KILLED,
}
/* -- The following fields are protected by stateLock -- */
private ChannelState state = ChannelState.UNINITIALIZED;
private ChannelState state;
/* Binding; Once bound the port will remain constant. */
int port = -1;
private HashSet<InetSocketAddress> localAddresses = new HashSet<InetSocketAddress>();
private final Set<InetSocketAddress> localAddresses = new HashSet<>();
/* Has the channel been bound to the wildcard address */
private boolean wildcard; /* false */
//private InetSocketAddress remoteAddress = null;
@ -225,7 +227,7 @@ public class SctpChannelImpl extends SctpChannel
return this;
}
private SctpChannel bindUnbindAddress(InetAddress address, boolean add)
private void bindUnbindAddress(InetAddress address, boolean add)
throws IOException {
if (address == null)
throw new IllegalArgumentException();
@ -281,12 +283,11 @@ public class SctpChannelImpl extends SctpChannel
}
}
}
return this;
}
private boolean isBound() {
synchronized (stateLock) {
return port == -1 ? false : true;
return port != -1;
}
}
@ -696,28 +697,22 @@ public class SctpChannelImpl extends SctpChannel
}
}
private static class DefaultOptionsHolder {
static final Set<SctpSocketOption<?>> defaultOptions = defaultOptions();
private static Set<SctpSocketOption<?>> defaultOptions() {
HashSet<SctpSocketOption<?>> set = new HashSet<SctpSocketOption<?>>(10);
set.add(SCTP_DISABLE_FRAGMENTS);
set.add(SCTP_EXPLICIT_COMPLETE);
set.add(SCTP_FRAGMENT_INTERLEAVE);
set.add(SCTP_INIT_MAXSTREAMS);
set.add(SCTP_NODELAY);
set.add(SCTP_PRIMARY_ADDR);
set.add(SCTP_SET_PEER_PRIMARY_ADDR);
set.add(SO_SNDBUF);
set.add(SO_RCVBUF);
set.add(SO_LINGER);
return Collections.unmodifiableSet(set);
}
}
@Override
public final Set<SctpSocketOption<?>> supportedOptions() {
return DefaultOptionsHolder.defaultOptions;
final class Holder {
static final Set<SctpSocketOption<?>> DEFAULT_OPTIONS = Set.of(
SCTP_DISABLE_FRAGMENTS,
SCTP_EXPLICIT_COMPLETE,
SCTP_FRAGMENT_INTERLEAVE,
SCTP_INIT_MAXSTREAMS,
SCTP_NODELAY,
SCTP_PRIMARY_ADDR,
SCTP_SET_PEER_PRIMARY_ADDR,
SO_SNDBUF,
SO_RCVBUF,
SO_LINGER);
}
return Holder.DEFAULT_OPTIONS;
}
@Override
@ -856,23 +851,20 @@ public class SctpChannelImpl extends SctpChannel
}
}
private InternalNotificationHandler internalNotificationHandler =
private final InternalNotificationHandler internalNotificationHandler =
new InternalNotificationHandler();
private void handleNotificationInternal(ResultContainer resultContainer)
{
private void handleNotificationInternal(ResultContainer resultContainer) {
invokeNotificationHandler(resultContainer,
internalNotificationHandler, null);
}
private class InternalNotificationHandler
extends AbstractNotificationHandler<Object>
{
private final class InternalNotificationHandler
extends AbstractNotificationHandler<Object> {
@Override
public HandlerResult handleNotification(
AssociationChangeNotification not, Object unused) {
if (not.event().equals(
AssociationChangeNotification.AssocChangeEvent.COMM_UP) &&
public HandlerResult handleNotification(AssociationChangeNotification not,
Object unused) {
if (not.event().equals(AssociationChangeNotification.AssocChangeEvent.COMM_UP) &&
association == null) {
AssociationChange sac = (AssociationChange) not;
association = new AssociationImpl
@ -882,8 +874,7 @@ public class SctpChannelImpl extends SctpChannel
}
}
private <T> HandlerResult invokeNotificationHandler
(ResultContainer resultContainer,
private <T> HandlerResult invokeNotificationHandler(ResultContainer resultContainer,
NotificationHandler<T> handler,
T attachment) {
SctpNotification notification = resultContainer.notification();
@ -891,31 +882,24 @@ public class SctpChannelImpl extends SctpChannel
notification.setAssociation(association);
}
if (!(handler instanceof AbstractNotificationHandler)) {
if (!(handler instanceof AbstractNotificationHandler<T> absHandler)) {
return handler.handleNotification(notification, attachment);
}
/* AbstractNotificationHandler */
AbstractNotificationHandler<T> absHandler =
(AbstractNotificationHandler<T>)handler;
switch(resultContainer.type()) {
case ASSOCIATION_CHANGED :
return absHandler.handleNotification(
return switch (resultContainer.type()) {
case ASSOCIATION_CHANGED -> absHandler.handleNotification(
resultContainer.getAssociationChanged(), attachment);
case PEER_ADDRESS_CHANGED :
return absHandler.handleNotification(
case PEER_ADDRESS_CHANGED -> absHandler.handleNotification(
resultContainer.getPeerAddressChanged(), attachment);
case SEND_FAILED :
return absHandler.handleNotification(
case SEND_FAILED -> absHandler.handleNotification(
resultContainer.getSendFailed(), attachment);
case SHUTDOWN :
return absHandler.handleNotification(
case SHUTDOWN -> absHandler.handleNotification(
resultContainer.getShutdown(), attachment);
default :
/* implementation specific handlers */
return absHandler.handleNotification(
default -> absHandler.handleNotification(
resultContainer.notification(), attachment);
}
};
}
private void checkAssociation(Association sendAssociation) {
@ -1113,8 +1097,8 @@ public class SctpChannelImpl extends SctpChannel
@SuppressWarnings("removal")
private static void loadSctpLibrary() {
IOUtil.load(); /* loads nio & net native libraries */
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
AccessController.doPrivileged(
new PrivilegedAction<>() {
public Void run() {
System.loadLibrary("sctp");
return null;

View File

@ -36,6 +36,7 @@ import java.util.Iterator;
import java.util.Set;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Map;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.ClosedChannelException;
@ -80,8 +81,8 @@ public class SctpMultiChannelImpl extends SctpMultiChannel
private final int fdVal;
/* IDs of native threads doing send and receives, for signalling */
private volatile long receiverThread = 0;
private volatile long senderThread = 0;
private volatile long receiverThread;
private volatile long senderThread;
/* Lock held by current receiving thread */
private final Object receiveLock = new Object();
@ -104,30 +105,25 @@ public class SctpMultiChannelImpl extends SctpMultiChannel
/* Binding: Once bound the port will remain constant. */
int port = -1;
private HashSet<InetSocketAddress> localAddresses = new HashSet<InetSocketAddress>();
private final Set<InetSocketAddress> localAddresses = new HashSet<>();
/* Has the channel been bound to the wildcard address */
private boolean wildcard; /* false */
/* Keeps a map of addresses to association, and visa versa */
private HashMap<SocketAddress, Association> addressMap =
new HashMap<SocketAddress, Association>();
private HashMap<Association, Set<SocketAddress>> associationMap =
new HashMap<Association, Set<SocketAddress>>();
/* Keeps a map of addresses to association, and vice versa */
private final Map<SocketAddress, Association> addressMap =
new HashMap<>();
private final Map<Association, Set<SocketAddress>> associationMap =
new HashMap<>();
/* -- End of fields protected by stateLock -- */
/* If an association has been shutdown mark it for removal after
* the user handler has been invoked */
private final ThreadLocal<Association> associationToRemove =
new ThreadLocal<Association>() {
@Override protected Association initialValue() {
return null;
}
};
private final ThreadLocal<Association> associationToRemove = new ThreadLocal<>();
/* A notification handler cannot invoke receive */
private final ThreadLocal<Boolean> receiveInvoked =
new ThreadLocal<Boolean>() {
new ThreadLocal<>() {
@Override protected Boolean initialValue() {
return Boolean.FALSE;
}
@ -259,7 +255,7 @@ public class SctpMultiChannelImpl extends SctpMultiChannel
private boolean isBound() {
synchronized (stateLock) {
return port == -1 ? false : true;
return port != -1;
}
}
@ -440,28 +436,23 @@ public class SctpMultiChannelImpl extends SctpMultiChannel
}
}
private static class DefaultOptionsHolder {
static final Set<SctpSocketOption<?>> defaultOptions = defaultOptions();
private static Set<SctpSocketOption<?>> defaultOptions() {
HashSet<SctpSocketOption<?>> set = new HashSet<SctpSocketOption<?>>(10);
set.add(SCTP_DISABLE_FRAGMENTS);
set.add(SCTP_EXPLICIT_COMPLETE);
set.add(SCTP_FRAGMENT_INTERLEAVE);
set.add(SCTP_INIT_MAXSTREAMS);
set.add(SCTP_NODELAY);
set.add(SCTP_PRIMARY_ADDR);
set.add(SCTP_SET_PEER_PRIMARY_ADDR);
set.add(SO_SNDBUF);
set.add(SO_RCVBUF);
set.add(SO_LINGER);
return Collections.unmodifiableSet(set);
}
}
@Override
public final Set<SctpSocketOption<?>> supportedOptions() {
return DefaultOptionsHolder.defaultOptions;
final class Holder {
static final Set<SctpSocketOption<?>> DEFAULT_OPTIONS = Set.of(
SCTP_DISABLE_FRAGMENTS,
SCTP_EXPLICIT_COMPLETE,
SCTP_FRAGMENT_INTERLEAVE,
SCTP_INIT_MAXSTREAMS,
SCTP_NODELAY,
SCTP_PRIMARY_ADDR,
SCTP_SET_PEER_PRIMARY_ADDR,
SO_SNDBUF,
SO_RCVBUF,
SO_LINGER);
}
return Holder.DEFAULT_OPTIONS;
}
@Override
@ -598,7 +589,7 @@ public class SctpMultiChannelImpl extends SctpMultiChannel
}
}
private InternalNotificationHandler internalNotificationHandler =
private final InternalNotificationHandler internalNotificationHandler =
new InternalNotificationHandler();
private void handleNotificationInternal(ResultContainer resultContainer)
@ -607,23 +598,22 @@ public class SctpMultiChannelImpl extends SctpMultiChannel
internalNotificationHandler, null);
}
private class InternalNotificationHandler
private final class InternalNotificationHandler
extends AbstractNotificationHandler<Object>
{
@Override
public HandlerResult handleNotification(
AssociationChangeNotification not, Object unused) {
public HandlerResult handleNotification(AssociationChangeNotification not,
Object unused) {
AssociationChange sac = (AssociationChange) not;
/* Update map to reflect change in association */
switch (not.event()) {
case COMM_UP :
case COMM_UP -> {
Association newAssociation = new AssociationImpl
(sac.assocId(), sac.maxInStreams(), sac.maxOutStreams());
addAssociation(newAssociation);
break;
case SHUTDOWN :
case COMM_LOST :
}
case SHUTDOWN, COMM_LOST ->
//case RESTART: ???
/* mark association for removal after user handler invoked*/
associationToRemove.set(lookupAssociation(sac.assocId()));
@ -632,41 +622,29 @@ public class SctpMultiChannelImpl extends SctpMultiChannel
}
}
private <T> HandlerResult invokeNotificationHandler(
ResultContainer resultContainer,
private <T> HandlerResult invokeNotificationHandler(ResultContainer resultContainer,
NotificationHandler<T> handler,
T attachment) {
HandlerResult result;
SctpNotification notification = resultContainer.notification();
notification.setAssociation(lookupAssociation(notification.assocId()));
if (!(handler instanceof AbstractNotificationHandler)) {
if (!(handler instanceof AbstractNotificationHandler<T> absHandler)) {
result = handler.handleNotification(notification, attachment);
} else { /* AbstractNotificationHandler */
AbstractNotificationHandler<T> absHandler =
(AbstractNotificationHandler<T>)handler;
switch(resultContainer.type()) {
case ASSOCIATION_CHANGED :
result = absHandler.handleNotification(
result = switch (resultContainer.type()) {
case ASSOCIATION_CHANGED -> absHandler.handleNotification(
resultContainer.getAssociationChanged(), attachment);
break;
case PEER_ADDRESS_CHANGED :
result = absHandler.handleNotification(
case PEER_ADDRESS_CHANGED -> absHandler.handleNotification(
resultContainer.getPeerAddressChanged(), attachment);
break;
case SEND_FAILED :
result = absHandler.handleNotification(
case SEND_FAILED -> absHandler.handleNotification(
resultContainer.getSendFailed(), attachment);
break;
case SHUTDOWN :
result = absHandler.handleNotification(
case SHUTDOWN -> absHandler.handleNotification(
resultContainer.getShutdown(), attachment);
break;
default :
/* implementation specific handlers */
result = absHandler.handleNotification(
default -> absHandler.handleNotification(
resultContainer.notification(), attachment);
}
};
}
if (!(handler instanceof InternalNotificationHandler)) {
@ -754,17 +732,15 @@ public class SctpMultiChannelImpl extends SctpMultiChannel
}
/**
* @throws IllegalArgumentException
* If the given association is not controlled by this channel
* Checks if the given association is controlled by this channel.
*
* @return {@code true} if, and only if, the given association is one
* of the current associations controlled by this channel
* @throws IllegalArgumentException If the given association is not controlled by this channel
*/
private boolean checkAssociation(Association messageAssoc) {
private void checkAssociation(Association messageAssoc) {
synchronized (stateLock) {
for (Association association : associationMap.keySet()) {
if (messageAssoc.equals(association)) {
return true;
return;
}
}
}
@ -967,8 +943,7 @@ public class SctpMultiChannelImpl extends SctpMultiChannel
return SctpNet.getRemoteAddresses(fdVal, association.associationID());
} catch (SocketException se) {
/* a valid association should always have remote addresses */
Set<SocketAddress> addrs = associationMap.get(association);
return addrs != null ? addrs : Collections.<SocketAddress>emptySet();
return associationMap.getOrDefault(association, Collections.emptySet());
}
}
}

View File

@ -132,11 +132,11 @@ public class SctpNet {
static Set<SocketAddress> getRemoteAddresses(int fd, int assocId)
throws IOException {
HashSet<SocketAddress> set = null;
Set<SocketAddress> set = null;
SocketAddress[] saa = getRemoteAddresses0(fd, assocId);
if (saa != null) {
set = new HashSet<SocketAddress>(saa.length);
set = new HashSet<>(saa.length);
for (SocketAddress sa : saa)
set.add(sa);
}
@ -160,8 +160,6 @@ public class SctpNet {
name.equals(SCTP_SET_PEER_PRIMARY_ADDR)) {
SocketAddress addr = (SocketAddress) value;
if (addr == null)
throw new IllegalArgumentException("Invalid option value");
Net.checkAddress(addr);
InetSocketAddress netAddr = (InetSocketAddress)addr;
@ -257,7 +255,7 @@ public class SctpNet {
arg = (b) ? 1 : 0;
}
setIntOption0(fd, ((SctpStdSocketOption)name).constValue(), arg);
setIntOption0(fd, ((SctpStdSocketOption<?>)name).constValue(), arg);
}
static Object getIntOption(int fd, SctpSocketOption<?> name)
@ -267,11 +265,10 @@ public class SctpNet {
if (type != Integer.class && type != Boolean.class)
throw new AssertionError("Should not reach here");
if (!(name instanceof SctpStdSocketOption))
if (!(name instanceof SctpStdSocketOption<?> option))
throw new AssertionError("Should not reach here");
int value = getIntOption0(fd,
((SctpStdSocketOption)name).constValue());
int value = getIntOption0(fd, option.constValue());
if (type == Integer.class) {
return Integer.valueOf(value);

View File

@ -28,8 +28,8 @@ import com.sun.nio.sctp.Association;
import com.sun.nio.sctp.Notification;
/**
* All Notification implemenations MUST implement this interface to provide
* access to the native association identidier.
* All Notification implementations MUST implement this interface to provide
* access to the native association identifier.
*/
interface SctpNotification extends Notification {
int assocId();

View File

@ -41,14 +41,12 @@ import com.sun.nio.sctp.SctpChannel;
import com.sun.nio.sctp.SctpServerChannel;
import com.sun.nio.sctp.SctpSocketOption;
import com.sun.nio.sctp.SctpStandardSocketOptions;
import sun.nio.ch.DirectBuffer;
import sun.nio.ch.NativeThread;
import sun.nio.ch.IOStatus;
import sun.nio.ch.IOUtil;
import sun.nio.ch.Net;
import sun.nio.ch.SelChImpl;
import sun.nio.ch.SelectionKeyImpl;
import sun.nio.ch.Util;
/**
* An implementation of SctpServerChannel
@ -61,7 +59,7 @@ public class SctpServerChannelImpl extends SctpServerChannel
private final int fdVal;
/* IDs of native thread doing accept, for signalling */
private volatile long thread = 0;
private volatile long thread;
/* Lock held by thread currently blocked in this channel */
private final Object lock = new Object();
@ -81,7 +79,7 @@ public class SctpServerChannelImpl extends SctpServerChannel
/* Binding: Once bound the port will remain constant. */
int port = -1;
private HashSet<InetSocketAddress> localAddresses = new HashSet<InetSocketAddress>();
private final HashSet<InetSocketAddress> localAddresses = new HashSet<>();
/* Has the channel been bound to the wildcard address */
private boolean wildcard; /* false */
@ -200,7 +198,7 @@ public class SctpServerChannelImpl extends SctpServerChannel
private boolean isBound() {
synchronized (stateLock) {
return port == -1 ? false : true;
return port != -1;
}
}
@ -389,19 +387,13 @@ public class SctpServerChannelImpl extends SctpServerChannel
}
}
private static class DefaultOptionsHolder {
static final Set<SctpSocketOption<?>> defaultOptions = defaultOptions();
private static Set<SctpSocketOption<?>> defaultOptions() {
HashSet<SctpSocketOption<?>> set = new HashSet<SctpSocketOption<?>>(1);
set.add(SctpStandardSocketOptions.SCTP_INIT_MAXSTREAMS);
return Collections.unmodifiableSet(set);
}
}
@Override
public final Set<SctpSocketOption<?>> supportedOptions() {
return DefaultOptionsHolder.defaultOptions;
final class Holder {
static final Set<SctpSocketOption<?>> DEFAULT_OPTIONS =
Set.of(SctpStandardSocketOptions.SCTP_INIT_MAXSTREAMS);
}
return Holder.DEFAULT_OPTIONS;
}
@Override

View File

@ -38,11 +38,11 @@ public class SendFailed extends SendFailedNotification
private Association association;
/* assocId is used to lookup the association before the notification is
* returned to user code */
private int assocId;
private SocketAddress address;
private ByteBuffer buffer;
private int errorCode;
private int streamNumber;
private final int assocId;
private final SocketAddress address;
private final ByteBuffer buffer;
private final int errorCode;
private final int streamNumber;
/* Invoked from native */
private SendFailed(int assocId,
@ -97,14 +97,12 @@ public class SendFailed extends SendFailedNotification
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(super.toString()).append(" [");
sb.append("Association:").append(association);
sb.append(", Address: ").append(address);
sb.append(", buffer: ").append(buffer);
sb.append(", errorCode: ").append(errorCode);
sb.append(", streamNumber: ").append(streamNumber);
sb.append("]");
return sb.toString();
return super.toString() + " [" +
"Association:" + association +
", Address: " + address +
", buffer: " + buffer +
", errorCode: " + errorCode +
", streamNumber: " + streamNumber +
"]";
}
}

View File

@ -34,9 +34,9 @@ public class Shutdown extends ShutdownNotification
implements SctpNotification
{
private Association association;
/* assocId is used to lookup the association before the notification is
/* assocId is used to look up the association before the notification is
* returned to user code */
private int assocId;
private final int assocId;
/* Invoked from native */
private Shutdown(int assocId) {
@ -61,9 +61,7 @@ public class Shutdown extends ShutdownNotification
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(super.toString()).append(" [");
sb.append("Association:").append(association).append("]");
return sb.toString();
return super.toString() + " [" +
"Association:" + association + "]";
}
}