move sctp to netty-contrib

main
Jörg Prante 7 months ago
parent 938371e9eb
commit 1b906bf706

@ -1,3 +1,3 @@
group = org.xbib.netty
name = netty
version = 4.1.105.0
version = 4.1.107.0

@ -1,3 +0,0 @@
dependencies {
api project(':netty-channel')
}

@ -1,245 +0,0 @@
/*
* Copyright 2011 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.channel.sctp;
import com.sun.nio.sctp.SctpChannel;
import com.sun.nio.sctp.SctpStandardSocketOptions;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelOption;
import io.netty.channel.DefaultChannelConfig;
import io.netty.channel.MessageSizeEstimator;
import io.netty.channel.RecvByteBufAllocator;
import io.netty.channel.WriteBufferWaterMark;
import io.netty.util.internal.ObjectUtil;
import io.netty.util.internal.PlatformDependent;
import java.io.IOException;
import java.util.Map;
import static io.netty.channel.ChannelOption.SO_RCVBUF;
import static io.netty.channel.ChannelOption.SO_SNDBUF;
import static io.netty.channel.sctp.SctpChannelOption.SCTP_INIT_MAXSTREAMS;
import static io.netty.channel.sctp.SctpChannelOption.SCTP_NODELAY;
/**
* The default {@link SctpChannelConfig} implementation for SCTP.
*/
public class DefaultSctpChannelConfig extends DefaultChannelConfig implements SctpChannelConfig {
private final SctpChannel javaChannel;
public DefaultSctpChannelConfig(io.netty.channel.sctp.SctpChannel channel, SctpChannel javaChannel) {
super(channel);
this.javaChannel = ObjectUtil.checkNotNull(javaChannel, "javaChannel");
// Enable TCP_NODELAY by default if possible.
if (PlatformDependent.canEnableTcpNoDelayByDefault()) {
try {
setSctpNoDelay(true);
} catch (Exception e) {
// Ignore.
}
}
}
@Override
public Map<ChannelOption<?>, Object> getOptions() {
return getOptions(
super.getOptions(),
SO_RCVBUF, SO_SNDBUF, SCTP_NODELAY, SCTP_INIT_MAXSTREAMS);
}
@SuppressWarnings("unchecked")
@Override
public <T> T getOption(ChannelOption<T> option) {
if (option == SO_RCVBUF) {
return (T) Integer.valueOf(getReceiveBufferSize());
}
if (option == SO_SNDBUF) {
return (T) Integer.valueOf(getSendBufferSize());
}
if (option == SCTP_NODELAY) {
return (T) Boolean.valueOf(isSctpNoDelay());
}
if (option == SCTP_INIT_MAXSTREAMS) {
return (T) getInitMaxStreams();
}
return super.getOption(option);
}
@Override
public <T> boolean setOption(ChannelOption<T> option, T value) {
validate(option, value);
if (option == SO_RCVBUF) {
setReceiveBufferSize((Integer) value);
} else if (option == SO_SNDBUF) {
setSendBufferSize((Integer) value);
} else if (option == SCTP_NODELAY) {
setSctpNoDelay((Boolean) value);
} else if (option == SCTP_INIT_MAXSTREAMS) {
setInitMaxStreams((SctpStandardSocketOptions.InitMaxStreams) value);
} else {
return super.setOption(option, value);
}
return true;
}
@Override
public boolean isSctpNoDelay() {
try {
return javaChannel.getOption(SctpStandardSocketOptions.SCTP_NODELAY);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public SctpChannelConfig setSctpNoDelay(boolean sctpNoDelay) {
try {
javaChannel.setOption(SctpStandardSocketOptions.SCTP_NODELAY, sctpNoDelay);
} catch (IOException e) {
throw new ChannelException(e);
}
return this;
}
@Override
public int getSendBufferSize() {
try {
return javaChannel.getOption(SctpStandardSocketOptions.SO_SNDBUF);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public SctpChannelConfig setSendBufferSize(int sendBufferSize) {
try {
javaChannel.setOption(SctpStandardSocketOptions.SO_SNDBUF, sendBufferSize);
} catch (IOException e) {
throw new ChannelException(e);
}
return this;
}
@Override
public int getReceiveBufferSize() {
try {
return javaChannel.getOption(SctpStandardSocketOptions.SO_RCVBUF);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public SctpChannelConfig setReceiveBufferSize(int receiveBufferSize) {
try {
javaChannel.setOption(SctpStandardSocketOptions.SO_RCVBUF, receiveBufferSize);
} catch (IOException e) {
throw new ChannelException(e);
}
return this;
}
@Override
public SctpStandardSocketOptions.InitMaxStreams getInitMaxStreams() {
try {
return javaChannel.getOption(SctpStandardSocketOptions.SCTP_INIT_MAXSTREAMS);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public SctpChannelConfig setInitMaxStreams(SctpStandardSocketOptions.InitMaxStreams initMaxStreams) {
try {
javaChannel.setOption(SctpStandardSocketOptions.SCTP_INIT_MAXSTREAMS, initMaxStreams);
} catch (IOException e) {
throw new ChannelException(e);
}
return this;
}
@Override
public SctpChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) {
super.setConnectTimeoutMillis(connectTimeoutMillis);
return this;
}
@Override
@Deprecated
public SctpChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) {
super.setMaxMessagesPerRead(maxMessagesPerRead);
return this;
}
@Override
public SctpChannelConfig setWriteSpinCount(int writeSpinCount) {
super.setWriteSpinCount(writeSpinCount);
return this;
}
@Override
public SctpChannelConfig setAllocator(ByteBufAllocator allocator) {
super.setAllocator(allocator);
return this;
}
@Override
public SctpChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) {
super.setRecvByteBufAllocator(allocator);
return this;
}
@Override
public SctpChannelConfig setAutoRead(boolean autoRead) {
super.setAutoRead(autoRead);
return this;
}
@Override
public SctpChannelConfig setAutoClose(boolean autoClose) {
super.setAutoClose(autoClose);
return this;
}
@Override
public SctpChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) {
super.setWriteBufferHighWaterMark(writeBufferHighWaterMark);
return this;
}
@Override
public SctpChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) {
super.setWriteBufferLowWaterMark(writeBufferLowWaterMark);
return this;
}
@Override
public SctpChannelConfig setWriteBufferWaterMark(WriteBufferWaterMark writeBufferWaterMark) {
super.setWriteBufferWaterMark(writeBufferWaterMark);
return this;
}
@Override
public SctpChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) {
super.setMessageSizeEstimator(estimator);
return this;
}
}

@ -1,227 +0,0 @@
/*
* Copyright 2011 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.channel.sctp;
import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero;
import com.sun.nio.sctp.SctpServerChannel;
import com.sun.nio.sctp.SctpStandardSocketOptions;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelOption;
import io.netty.channel.DefaultChannelConfig;
import io.netty.channel.MessageSizeEstimator;
import io.netty.channel.RecvByteBufAllocator;
import io.netty.channel.ServerChannelRecvByteBufAllocator;
import io.netty.channel.WriteBufferWaterMark;
import io.netty.util.NetUtil;
import io.netty.util.internal.ObjectUtil;
import java.io.IOException;
import java.util.Map;
/**
* The default {@link SctpServerChannelConfig} implementation for SCTP.
*/
public class DefaultSctpServerChannelConfig extends DefaultChannelConfig implements SctpServerChannelConfig {
private final SctpServerChannel javaChannel;
private volatile int backlog = NetUtil.SOMAXCONN;
/**
* Creates a new instance.
*/
public DefaultSctpServerChannelConfig(
io.netty.channel.sctp.SctpServerChannel channel, SctpServerChannel javaChannel) {
super(channel, new ServerChannelRecvByteBufAllocator());
this.javaChannel = ObjectUtil.checkNotNull(javaChannel, "javaChannel");
}
@Override
public Map<ChannelOption<?>, Object> getOptions() {
return getOptions(
super.getOptions(),
ChannelOption.SO_RCVBUF, ChannelOption.SO_SNDBUF, SctpChannelOption.SCTP_INIT_MAXSTREAMS);
}
@SuppressWarnings("unchecked")
@Override
public <T> T getOption(ChannelOption<T> option) {
if (option == ChannelOption.SO_RCVBUF) {
return (T) Integer.valueOf(getReceiveBufferSize());
}
if (option == ChannelOption.SO_SNDBUF) {
return (T) Integer.valueOf(getSendBufferSize());
}
if (option == SctpChannelOption.SCTP_INIT_MAXSTREAMS) {
return (T) getInitMaxStreams();
}
return super.getOption(option);
}
@Override
public <T> boolean setOption(ChannelOption<T> option, T value) {
validate(option, value);
if (option == ChannelOption.SO_RCVBUF) {
setReceiveBufferSize((Integer) value);
} else if (option == ChannelOption.SO_SNDBUF) {
setSendBufferSize((Integer) value);
} else if (option == SctpChannelOption.SCTP_INIT_MAXSTREAMS) {
setInitMaxStreams((SctpStandardSocketOptions.InitMaxStreams) value);
} else {
return super.setOption(option, value);
}
return true;
}
@Override
public int getSendBufferSize() {
try {
return javaChannel.getOption(SctpStandardSocketOptions.SO_SNDBUF);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public SctpServerChannelConfig setSendBufferSize(int sendBufferSize) {
try {
javaChannel.setOption(SctpStandardSocketOptions.SO_SNDBUF, sendBufferSize);
} catch (IOException e) {
throw new ChannelException(e);
}
return this;
}
@Override
public int getReceiveBufferSize() {
try {
return javaChannel.getOption(SctpStandardSocketOptions.SO_RCVBUF);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public SctpServerChannelConfig setReceiveBufferSize(int receiveBufferSize) {
try {
javaChannel.setOption(SctpStandardSocketOptions.SO_RCVBUF, receiveBufferSize);
} catch (IOException e) {
throw new ChannelException(e);
}
return this;
}
@Override
public SctpStandardSocketOptions.InitMaxStreams getInitMaxStreams() {
try {
return javaChannel.getOption(SctpStandardSocketOptions.SCTP_INIT_MAXSTREAMS);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public SctpServerChannelConfig setInitMaxStreams(SctpStandardSocketOptions.InitMaxStreams initMaxStreams) {
try {
javaChannel.setOption(SctpStandardSocketOptions.SCTP_INIT_MAXSTREAMS, initMaxStreams);
} catch (IOException e) {
throw new ChannelException(e);
}
return this;
}
@Override
public int getBacklog() {
return backlog;
}
@Override
public SctpServerChannelConfig setBacklog(int backlog) {
checkPositiveOrZero(backlog, "backlog");
this.backlog = backlog;
return this;
}
@Override
@Deprecated
public SctpServerChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) {
super.setMaxMessagesPerRead(maxMessagesPerRead);
return this;
}
@Override
public SctpServerChannelConfig setWriteSpinCount(int writeSpinCount) {
super.setWriteSpinCount(writeSpinCount);
return this;
}
@Override
public SctpServerChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) {
super.setConnectTimeoutMillis(connectTimeoutMillis);
return this;
}
@Override
public SctpServerChannelConfig setAllocator(ByteBufAllocator allocator) {
super.setAllocator(allocator);
return this;
}
@Override
public SctpServerChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) {
super.setRecvByteBufAllocator(allocator);
return this;
}
@Override
public SctpServerChannelConfig setAutoRead(boolean autoRead) {
super.setAutoRead(autoRead);
return this;
}
@Override
public SctpServerChannelConfig setAutoClose(boolean autoClose) {
super.setAutoClose(autoClose);
return this;
}
@Override
public SctpServerChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) {
super.setWriteBufferLowWaterMark(writeBufferLowWaterMark);
return this;
}
@Override
public SctpServerChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) {
super.setWriteBufferHighWaterMark(writeBufferHighWaterMark);
return this;
}
@Override
public SctpServerChannelConfig setWriteBufferWaterMark(WriteBufferWaterMark writeBufferWaterMark) {
super.setWriteBufferWaterMark(writeBufferWaterMark);
return this;
}
@Override
public SctpServerChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) {
super.setMessageSizeEstimator(estimator);
return this;
}
}

@ -1,114 +0,0 @@
/*
* Copyright 2011 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.channel.sctp;
import com.sun.nio.sctp.Association;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelPromise;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Set;
/**
* A SCTP/IP {@link Channel} interface for single SCTP association.
*
* <p>
* The SctpChannel is a message-oriented, connected transport which supports multi-streaming and multi-homing.
* </p>
*/
public interface SctpChannel extends Channel {
@Override
SctpServerChannel parent();
/**
* Returns the underlying SCTP association.
*/
Association association();
/**
* Return the (primary) local address of the SCTP channel.
*
* Please note that, this return the first local address in the underlying SCTP Channel's
* local address iterator to support Netty Channel API. In other words, its the application's
* responsibility to keep track of it's local primary address.
*
* (To set a local address as primary, the application can request by calling local SCTP stack,
* with SctpStandardSocketOption.SCTP_PRIMARY_ADDR option).
*/
@Override
InetSocketAddress localAddress();
/**
* Return all local addresses of the SCTP channel.
* Please note that, it will return more than one address if this channel is using multi-homing
*/
Set<InetSocketAddress> allLocalAddresses();
/**
* Returns the {@link SctpChannelConfig} configuration of the channel.
*/
@Override
SctpChannelConfig config();
/**
* Return the (primary) remote address of the SCTP channel.
*
* Please note that, this return the first remote address in the underlying SCTP Channel's
* remote address iterator to support Netty Channel API. In other words, its the application's
* responsibility to keep track of it's peer's primary address.
*
* (The application can request it's remote peer to set a specific address as primary by
* calling the local SCTP stack with SctpStandardSocketOption.SCTP_SET_PEER_PRIMARY_ADDR option)
*/
@Override
InetSocketAddress remoteAddress();
/**
* Return all remote addresses of the SCTP server channel.
* Please note that, it will return more than one address if the remote is using multi-homing.
*/
Set<InetSocketAddress> allRemoteAddresses();
/**
* Bind a address to the already bound channel to enable multi-homing.
* The Channel bust be bound and yet to be connected.
*/
ChannelFuture bindAddress(InetAddress localAddress);
/**
* Bind a address to the already bound channel to enable multi-homing.
* The Channel bust be bound and yet to be connected.
*
* Will notify the given {@link ChannelPromise} and return a {@link ChannelFuture}
*/
ChannelFuture bindAddress(InetAddress localAddress, ChannelPromise promise);
/**
* Unbind the address from channel's multi-homing address list.
* The address should be added already in multi-homing address list.
*/
ChannelFuture unbindAddress(InetAddress localAddress);
/**
* Unbind the address from channel's multi-homing address list.
* The address should be added already in multi-homing address list.
*
* Will notify the given {@link ChannelPromise} and return a {@link ChannelFuture}
*/
ChannelFuture unbindAddress(InetAddress localAddress, ChannelPromise promise);
}

@ -1,135 +0,0 @@
/*
* Copyright 2011 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.channel.sctp;
import com.sun.nio.sctp.SctpStandardSocketOptions.InitMaxStreams;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelConfig;
import io.netty.channel.ChannelOption;
import io.netty.channel.MessageSizeEstimator;
import io.netty.channel.RecvByteBufAllocator;
import io.netty.channel.WriteBufferWaterMark;
/**
* A {@link ChannelConfig} for a {@link SctpChannel}.
* <p/>
* <h3>Available options</h3>
* <p/>
* In addition to the options provided by {@link ChannelConfig},
* {@link SctpChannelConfig} allows the following options in the option map:
* <p/>
* <table border="1" cellspacing="0" cellpadding="6">
* <tr>
* <th>Name</th><th>Associated setter method</th>
* </tr><tr>
* <td>{@link ChannelOption#SO_RCVBUF}</td><td>{@link #setReceiveBufferSize(int)}</td>
* </tr><tr>
* <td>{@link ChannelOption#SO_SNDBUF}</td><td>{@link #setSendBufferSize(int)}</td>
* </tr><tr>
* <td>{@link SctpChannelOption#SCTP_NODELAY}</td><td>{@link #setSctpNoDelay(boolean)}}</td>
* </tr><tr>
* <td>{@link SctpChannelOption#SCTP_INIT_MAXSTREAMS}</td><td>{@link #setInitMaxStreams(InitMaxStreams)}</td>
* </tr>
* </table>
*/
public interface SctpChannelConfig extends ChannelConfig {
/**
* Gets the <a href="https://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SCTP_NODELAY}</a> option. Please note that the default value of this option is {@code true} unlike the
* operating system default ({@code false}). However, for some buggy platforms, such as Android, that shows erratic
* behavior with Nagle's algorithm disabled, the default value remains to be {@code false}.
*/
boolean isSctpNoDelay();
/**
* Sets the <a href="https://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SCTP_NODELAY}</a> option. Please note that the default value of this option is {@code true} unlike the
* operating system default ({@code false}). However, for some buggy platforms, such as Android, that shows erratic
* behavior with Nagle's algorithm disabled, the default value remains to be {@code false}.
*/
SctpChannelConfig setSctpNoDelay(boolean sctpNoDelay);
/**
* Gets the <a href="https://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SO_SNDBUF}</a> option.
*/
int getSendBufferSize();
/**
* Sets the <a href="https://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SO_SNDBUF}</a> option.
*/
SctpChannelConfig setSendBufferSize(int sendBufferSize);
/**
* Gets the <a href="https://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SO_RCVBUF}</a> option.
*/
int getReceiveBufferSize();
/**
* Gets the <a href="https://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SO_RCVBUF}</a> option.
*/
SctpChannelConfig setReceiveBufferSize(int receiveBufferSize);
/**
* Gets the <a href="https://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SCTP_INIT_MAXSTREAMS}</a> option.
*/
InitMaxStreams getInitMaxStreams();
/**
* Gets the <a href="https://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SCTP_INIT_MAXSTREAMS}</a> option.
*/
SctpChannelConfig setInitMaxStreams(InitMaxStreams initMaxStreams);
@Override
SctpChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis);
@Override
@Deprecated
SctpChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead);
@Override
SctpChannelConfig setWriteSpinCount(int writeSpinCount);
@Override
SctpChannelConfig setAllocator(ByteBufAllocator allocator);
@Override
SctpChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator);
@Override
SctpChannelConfig setAutoRead(boolean autoRead);
@Override
SctpChannelConfig setAutoClose(boolean autoClose);
@Override
SctpChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark);
@Override
SctpChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark);
@Override
SctpChannelConfig setWriteBufferWaterMark(WriteBufferWaterMark writeBufferWaterMark);
@Override
SctpChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator);
}

@ -1,48 +0,0 @@
/*
* Copyright 2013 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.channel.sctp;
import com.sun.nio.sctp.SctpStandardSocketOptions.InitMaxStreams;
import io.netty.channel.ChannelOption;
import java.net.SocketAddress;
/**
* Option for configuring the SCTP transport
*/
public final class SctpChannelOption<T> extends ChannelOption<T> {
public static final ChannelOption<Boolean> SCTP_DISABLE_FRAGMENTS =
valueOf(SctpChannelOption.class, "SCTP_DISABLE_FRAGMENTS");
public static final ChannelOption<Boolean> SCTP_EXPLICIT_COMPLETE =
valueOf(SctpChannelOption.class, "SCTP_EXPLICIT_COMPLETE");
public static final ChannelOption<Integer> SCTP_FRAGMENT_INTERLEAVE =
valueOf(SctpChannelOption.class, "SCTP_FRAGMENT_INTERLEAVE");
public static final ChannelOption<InitMaxStreams> SCTP_INIT_MAXSTREAMS =
valueOf(SctpChannelOption.class, "SCTP_INIT_MAXSTREAMS");
public static final ChannelOption<Boolean> SCTP_NODELAY =
valueOf(SctpChannelOption.class, "SCTP_NODELAY");
public static final ChannelOption<SocketAddress> SCTP_PRIMARY_ADDR =
valueOf(SctpChannelOption.class, "SCTP_PRIMARY_ADDR");
public static final ChannelOption<SocketAddress> SCTP_SET_PEER_PRIMARY_ADDR =
valueOf(SctpChannelOption.class, "SCTP_SET_PEER_PRIMARY_ADDR");
@SuppressWarnings({ "unused", "deprecation" })
private SctpChannelOption() {
super(null);
}
}

@ -1,204 +0,0 @@
/*
* Copyright 2011 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.channel.sctp;
import com.sun.nio.sctp.MessageInfo;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.DefaultByteBufHolder;
import io.netty.util.internal.ObjectUtil;
/**
* Representation of SCTP Data Chunk
*/
public final class SctpMessage extends DefaultByteBufHolder {
private final int streamIdentifier;
private final int protocolIdentifier;
private final boolean unordered;
private final MessageInfo msgInfo;
/**
* Essential data that is being carried within SCTP Data Chunk
* @param protocolIdentifier of payload
* @param streamIdentifier that you want to send the payload
* @param payloadBuffer channel buffer
*/
public SctpMessage(int protocolIdentifier, int streamIdentifier, ByteBuf payloadBuffer) {
this(protocolIdentifier, streamIdentifier, false, payloadBuffer);
}
/**
* Essential data that is being carried within SCTP Data Chunk
* @param protocolIdentifier of payload
* @param streamIdentifier that you want to send the payload
* @param unordered if {@literal true}, the SCTP Data Chunk will be sent with the U (unordered) flag set.
* @param payloadBuffer channel buffer
*/
public SctpMessage(int protocolIdentifier, int streamIdentifier, boolean unordered, ByteBuf payloadBuffer) {
super(payloadBuffer);
this.protocolIdentifier = protocolIdentifier;
this.streamIdentifier = streamIdentifier;
this.unordered = unordered;
msgInfo = null;
}
/**
* Essential data that is being carried within SCTP Data Chunk
* @param msgInfo the {@link MessageInfo}
* @param payloadBuffer channel buffer
*/
public SctpMessage(MessageInfo msgInfo, ByteBuf payloadBuffer) {
super(payloadBuffer);
this.msgInfo = ObjectUtil.checkNotNull(msgInfo, "msgInfo");
this.streamIdentifier = msgInfo.streamNumber();
this.protocolIdentifier = msgInfo.payloadProtocolID();
this.unordered = msgInfo.isUnordered();
}
/**
* Return the stream-identifier
*/
public int streamIdentifier() {
return streamIdentifier;
}
/**
* Return the protocol-identifier
*/
public int protocolIdentifier() {
return protocolIdentifier;
}
/**
* return the unordered flag
*/
public boolean isUnordered() {
return unordered;
}
/**
* Return the {@link MessageInfo} for inbound messages or {@code null} for
* outbound messages.
*/
public MessageInfo messageInfo() {
return msgInfo;
}
/**
* Return {@code true} if this message is complete.
*/
public boolean isComplete() {
if (msgInfo != null) {
return msgInfo.isComplete();
} else {
//all outbound sctp messages are complete
return true;
}
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
SctpMessage sctpFrame = (SctpMessage) o;
if (protocolIdentifier != sctpFrame.protocolIdentifier) {
return false;
}
if (streamIdentifier != sctpFrame.streamIdentifier) {
return false;
}
if (unordered != sctpFrame.unordered) {
return false;
}
return content().equals(sctpFrame.content());
}
@Override
public int hashCode() {
int result = streamIdentifier;
result = 31 * result + protocolIdentifier;
// values 1231 and 1237 are referenced in the javadocs of Boolean#hashCode()
result = 31 * result + (unordered ? 1231 : 1237);
result = 31 * result + content().hashCode();
return result;
}
@Override
public SctpMessage copy() {
return (SctpMessage) super.copy();
}
@Override
public SctpMessage duplicate() {
return (SctpMessage) super.duplicate();
}
@Override
public SctpMessage retainedDuplicate() {
return (SctpMessage) super.retainedDuplicate();
}
@Override
public SctpMessage replace(ByteBuf content) {
if (msgInfo == null) {
return new SctpMessage(protocolIdentifier, streamIdentifier, unordered, content);
} else {
return new SctpMessage(msgInfo, content);
}
}
@Override
public SctpMessage retain() {
super.retain();
return this;
}
@Override
public SctpMessage retain(int increment) {
super.retain(increment);
return this;
}
@Override
public SctpMessage touch() {
super.touch();
return this;
}
@Override
public SctpMessage touch(Object hint) {
super.touch(hint);
return this;
}
@Override
public String toString() {
return "SctpFrame{" +
"streamIdentifier=" + streamIdentifier + ", protocolIdentifier=" + protocolIdentifier +
", unordered=" + unordered +
", data=" + contentToString() + '}';
}
}

@ -1,70 +0,0 @@
/*
* Copyright 2011 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.channel.sctp;
import com.sun.nio.sctp.AbstractNotificationHandler;
import com.sun.nio.sctp.AssociationChangeNotification;
import com.sun.nio.sctp.HandlerResult;
import com.sun.nio.sctp.Notification;
import com.sun.nio.sctp.PeerAddressChangeNotification;
import com.sun.nio.sctp.SendFailedNotification;
import com.sun.nio.sctp.ShutdownNotification;
import io.netty.channel.ChannelPipeline;
import io.netty.util.internal.ObjectUtil;
/**
* {@link AbstractNotificationHandler} implementation which will handle all {@link Notification}s by trigger a
* {@link Notification} user event in the {@link ChannelPipeline} of a {@link SctpChannel}.
*/
public final class SctpNotificationHandler extends AbstractNotificationHandler<Object> {
private final SctpChannel sctpChannel;
public SctpNotificationHandler(SctpChannel sctpChannel) {
this.sctpChannel = ObjectUtil.checkNotNull(sctpChannel, "sctpChannel");
}
@Override
public HandlerResult handleNotification(AssociationChangeNotification notification, Object o) {
fireEvent(notification);
return HandlerResult.CONTINUE;
}
@Override
public HandlerResult handleNotification(PeerAddressChangeNotification notification, Object o) {
fireEvent(notification);
return HandlerResult.CONTINUE;
}
@Override
public HandlerResult handleNotification(SendFailedNotification notification, Object o) {
fireEvent(notification);
return HandlerResult.CONTINUE;
}
@Override
public HandlerResult handleNotification(ShutdownNotification notification, Object o) {
fireEvent(notification);
sctpChannel.close();
return HandlerResult.RETURN;
}
private void fireEvent(Notification notification) {
sctpChannel.pipeline().fireUserEventTriggered(notification);
}
}

@ -1,87 +0,0 @@
/*
* Copyright 2011 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.channel.sctp;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelPromise;
import io.netty.channel.ServerChannel;
import java.net.InetSocketAddress;
import java.net.InetAddress;
import java.util.Set;
/**
* A SCTP/IP {@link ServerChannel} which accepts incoming SCTP/IP associations.
*
* <p>
* Multi-homing address binding/unbinding can done through bindAddress/unbindAddress methods.
* </p>
*/
public interface SctpServerChannel extends ServerChannel {
/**
* Returns the {@link SctpServerChannelConfig} configuration of the channel.
*/
@Override
SctpServerChannelConfig config();
/**
* Return the (primary) local address of the SCTP server channel.
*
* Please note that, this return the first local address in the underlying SCTP ServerChannel's
* local address iterator to support Netty Channel API. In other words, its the application's
* responsibility to keep track of it's local primary address.
*
* (To set a local address as primary, the application can request by calling local SCTP stack,
* with SctpStandardSocketOption.SCTP_PRIMARY_ADDR option).
*/
@Override
InetSocketAddress localAddress();
/**
* Return all local addresses of the SCTP server channel.
* Please note that, it will return more than one address if this channel is using multi-homing
*/
Set<InetSocketAddress> allLocalAddresses();
/**
* Bind a address to the already bound channel to enable multi-homing.
* The Channel must be bound and yet to be connected.
*/
ChannelFuture bindAddress(InetAddress localAddress);
/**
* Bind a address to the already bound channel to enable multi-homing.
* The Channel must be bound and yet to be connected.
*
* Will notify the given {@link ChannelPromise} and return a {@link ChannelFuture}
*/
ChannelFuture bindAddress(InetAddress localAddress, ChannelPromise promise);
/**
* Unbind the address from channel's multi-homing address list.
* The address should be added already in multi-homing address list.
*/
ChannelFuture unbindAddress(InetAddress localAddress);
/**
* Unbind the address from channel's multi-homing address list.
* The address should be added already in multi-homing address list.
*
* Will notify the given {@link ChannelPromise} and return a {@link ChannelFuture}
*/
ChannelFuture unbindAddress(InetAddress localAddress, ChannelPromise promise);
}

@ -1,130 +0,0 @@
/*
* Copyright 2011 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.channel.sctp;
import com.sun.nio.sctp.SctpStandardSocketOptions.InitMaxStreams;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelConfig;
import io.netty.channel.ChannelOption;
import io.netty.channel.MessageSizeEstimator;
import io.netty.channel.RecvByteBufAllocator;
import io.netty.channel.WriteBufferWaterMark;
/**
* A {@link ChannelConfig} for a {@link SctpServerChannelConfig}.
* <p/>
* <h3>Available options</h3>
* <p/>
* In addition to the options provided by {@link ChannelConfig},
* {@link SctpServerChannelConfig} allows the following options in the
* option map:
* <p/>
* <table border="1" cellspacing="0" cellpadding="6">
* <tr>
* <th>Name</th><th>Associated setter method</th>
* </tr><tr>
* <td>{@link ChannelOption#SO_BACKLOG}</td><td>{@link #setBacklog(int)}</td>
* </tr><tr>
* <td>{@link ChannelOption#SO_RCVBUF}</td><td>{@link #setReceiveBufferSize(int)}</td>
* </tr><tr>
* <td>{@link ChannelOption#SO_SNDBUF}</td><td>{@link #setSendBufferSize(int)}</td>
* </tr><tr>
* <td>{@link SctpChannelOption#SCTP_INIT_MAXSTREAMS}</td><td>{@link #setInitMaxStreams(InitMaxStreams)}</td>
* </tr>
* </table>
*/
public interface SctpServerChannelConfig extends ChannelConfig {
/**
* Gets the backlog value to specify when the channel binds to a local address.
*/
int getBacklog();
/**
* Sets the backlog value to specify when the channel binds to a local address.
*/
SctpServerChannelConfig setBacklog(int backlog);
/**
* Gets the <a href="https://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SO_SNDBUF}</a> option.
*/
int getSendBufferSize();
/**
* Sets the <a href="https://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SO_SNDBUF}</a> option.
*/
SctpServerChannelConfig setSendBufferSize(int sendBufferSize);
/**
* Gets the <a href="https://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SO_RCVBUF}</a> option.
*/
int getReceiveBufferSize();
/**
* Gets the <a href="https://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SO_RCVBUF}</a> option.
*/
SctpServerChannelConfig setReceiveBufferSize(int receiveBufferSize);
/**
* Gets the <a href="https://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SCTP_INIT_MAXSTREAMS}</a> option.
*/
InitMaxStreams getInitMaxStreams();
/**
* Gets the <a href="https://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SCTP_INIT_MAXSTREAMS}</a> option.
*/
SctpServerChannelConfig setInitMaxStreams(InitMaxStreams initMaxStreams);
@Override
@Deprecated
SctpServerChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead);
@Override
SctpServerChannelConfig setWriteSpinCount(int writeSpinCount);
@Override
SctpServerChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis);
@Override
SctpServerChannelConfig setAllocator(ByteBufAllocator allocator);
@Override
SctpServerChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator);
@Override
SctpServerChannelConfig setAutoRead(boolean autoRead);
@Override
SctpServerChannelConfig setAutoClose(boolean autoClose);
@Override
SctpServerChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark);
@Override
SctpServerChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark);
@Override
SctpServerChannelConfig setWriteBufferWaterMark(WriteBufferWaterMark writeBufferWaterMark);
@Override
SctpServerChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator);
}

@ -1,401 +0,0 @@
/*
* Copyright 2011 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.channel.sctp.nio;
import com.sun.nio.sctp.Association;
import com.sun.nio.sctp.MessageInfo;
import com.sun.nio.sctp.NotificationHandler;
import com.sun.nio.sctp.SctpChannel;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelMetadata;
import io.netty.channel.ChannelOutboundBuffer;
import io.netty.channel.ChannelPromise;
import io.netty.channel.RecvByteBufAllocator;
import io.netty.channel.nio.AbstractNioMessageChannel;
import io.netty.channel.sctp.DefaultSctpChannelConfig;
import io.netty.channel.sctp.SctpChannelConfig;
import io.netty.channel.sctp.SctpMessage;
import io.netty.channel.sctp.SctpNotificationHandler;
import io.netty.channel.sctp.SctpServerChannel;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.StringUtil;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/**
* {@link io.netty.channel.sctp.SctpChannel} implementation which use non-blocking mode and allows to read /
* write {@link SctpMessage}s to the underlying {@link SctpChannel}.
*
* Be aware that not all operations systems support SCTP. Please refer to the documentation of your operation system,
* to understand what you need to do to use it. Also this feature is only supported on Java 7+.
*/
public class NioSctpChannel extends AbstractNioMessageChannel implements io.netty.channel.sctp.SctpChannel {
private static final ChannelMetadata METADATA = new ChannelMetadata(false);
private static final InternalLogger logger = InternalLoggerFactory.getInstance(NioSctpChannel.class);
private final SctpChannelConfig config;
private final NotificationHandler<?> notificationHandler;
private static SctpChannel newSctpChannel() {
try {
return SctpChannel.open();
} catch (IOException e) {
throw new ChannelException("Failed to open a sctp channel.", e);
}
}
/**
* Create a new instance
*/
public NioSctpChannel() {
this(newSctpChannel());
}
/**
* Create a new instance using {@link SctpChannel}
*/
public NioSctpChannel(SctpChannel sctpChannel) {
this(null, sctpChannel);
}
/**
* Create a new instance
*
* @param parent the {@link Channel} which is the parent of this {@link NioSctpChannel}
* or {@code null}.
* @param sctpChannel the underlying {@link SctpChannel}
*/
public NioSctpChannel(Channel parent, SctpChannel sctpChannel) {
super(parent, sctpChannel, SelectionKey.OP_READ);
try {
sctpChannel.configureBlocking(false);
config = new NioSctpChannelConfig(this, sctpChannel);
notificationHandler = new SctpNotificationHandler(this);
} catch (IOException e) {
try {
sctpChannel.close();
} catch (IOException e2) {
if (logger.isWarnEnabled()) {
logger.warn(
"Failed to close a partially initialized sctp channel.", e2);
}
}
throw new ChannelException("Failed to enter non-blocking mode.", e);
}
}
@Override
public InetSocketAddress localAddress() {
return (InetSocketAddress) super.localAddress();
}
@Override
public InetSocketAddress remoteAddress() {
return (InetSocketAddress) super.remoteAddress();
}
@Override
public SctpServerChannel parent() {
return (SctpServerChannel) super.parent();
}
@Override
public ChannelMetadata metadata() {
return METADATA;
}
@Override
public Association association() {
try {
return javaChannel().association();
} catch (IOException ignored) {
return null;
}
}
@Override
public Set<InetSocketAddress> allLocalAddresses() {
try {
final Set<SocketAddress> allLocalAddresses = javaChannel().getAllLocalAddresses();
final Set<InetSocketAddress> addresses = new LinkedHashSet<InetSocketAddress>(allLocalAddresses.size());
for (SocketAddress socketAddress : allLocalAddresses) {
addresses.add((InetSocketAddress) socketAddress);
}
return addresses;
} catch (Throwable ignored) {
return Collections.emptySet();
}
}
@Override
public SctpChannelConfig config() {
return config;
}
@Override
public Set<InetSocketAddress> allRemoteAddresses() {
try {
final Set<SocketAddress> allLocalAddresses = javaChannel().getRemoteAddresses();
final Set<InetSocketAddress> addresses = new HashSet<InetSocketAddress>(allLocalAddresses.size());
for (SocketAddress socketAddress : allLocalAddresses) {
addresses.add((InetSocketAddress) socketAddress);
}
return addresses;
} catch (Throwable ignored) {
return Collections.emptySet();
}
}
@Override
protected SctpChannel javaChannel() {
return (SctpChannel) super.javaChannel();
}
@Override
public boolean isActive() {
SctpChannel ch = javaChannel();
return ch.isOpen() && association() != null;
}
@Override
protected SocketAddress localAddress0() {
try {
Iterator<SocketAddress> i = javaChannel().getAllLocalAddresses().iterator();
if (i.hasNext()) {
return i.next();
}
} catch (IOException e) {
// ignore
}
return null;
}
@Override
protected SocketAddress remoteAddress0() {
try {
Iterator<SocketAddress> i = javaChannel().getRemoteAddresses().iterator();
if (i.hasNext()) {
return i.next();
}
} catch (IOException e) {
// ignore
}
return null;
}
@Override
protected void doBind(SocketAddress localAddress) throws Exception {
javaChannel().bind(localAddress);
}
@Override
protected boolean doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception {
if (localAddress != null) {
javaChannel().bind(localAddress);
}
boolean success = false;
try {
boolean connected = javaChannel().connect(remoteAddress);
if (!connected) {
selectionKey().interestOps(SelectionKey.OP_CONNECT);
}
success = true;
return connected;
} finally {
if (!success) {
doClose();
}
}
}
@Override
protected void doFinishConnect() throws Exception {
if (!javaChannel().finishConnect()) {
throw new Error();
}
}
@Override
protected void doDisconnect() throws Exception {
doClose();
}
@Override
protected void doClose() throws Exception {
javaChannel().close();
}
@Override
protected int doReadMessages(List<Object> buf) throws Exception {
SctpChannel ch = javaChannel();
RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();
ByteBuf buffer = allocHandle.allocate(config().getAllocator());
boolean free = true;
try {
ByteBuffer data = buffer.internalNioBuffer(buffer.writerIndex(), buffer.writableBytes());
int pos = data.position();
MessageInfo messageInfo = ch.receive(data, null, notificationHandler);
if (messageInfo == null) {
return 0;
}
allocHandle.lastBytesRead(data.position() - pos);
buf.add(new SctpMessage(messageInfo,
buffer.writerIndex(buffer.writerIndex() + allocHandle.lastBytesRead())));
free = false;
return 1;
} catch (Throwable cause) {
PlatformDependent.throwException(cause);
return -1;
} finally {
if (free) {
buffer.release();
}
}
}
@Override
protected boolean doWriteMessage(Object msg, ChannelOutboundBuffer in) throws Exception {
SctpMessage packet = (SctpMessage) msg;
ByteBuf data = packet.content();
int dataLen = data.readableBytes();
if (dataLen == 0) {
return true;
}
ByteBufAllocator alloc = alloc();
boolean needsCopy = data.nioBufferCount() != 1;
if (!needsCopy) {
if (!data.isDirect() && alloc.isDirectBufferPooled()) {
needsCopy = true;
}
}
ByteBuffer nioData;
if (needsCopy) {
data = alloc.directBuffer(dataLen).writeBytes(data);
}
nioData = data.nioBuffer();
final MessageInfo mi = MessageInfo.createOutgoing(association(), null, packet.streamIdentifier());
mi.payloadProtocolID(packet.protocolIdentifier());
mi.streamNumber(packet.streamIdentifier());
mi.unordered(packet.isUnordered());
final int writtenBytes = javaChannel().send(nioData, mi);
return writtenBytes > 0;
}
@Override
protected final Object filterOutboundMessage(Object msg) throws Exception {
if (msg instanceof SctpMessage) {
SctpMessage m = (SctpMessage) msg;
ByteBuf buf = m.content();
if (buf.isDirect() && buf.nioBufferCount() == 1) {
return m;
}
return new SctpMessage(m.protocolIdentifier(), m.streamIdentifier(), m.isUnordered(),
newDirectBuffer(m, buf));
}
throw new UnsupportedOperationException(
"unsupported message type: " + StringUtil.simpleClassName(msg) +
" (expected: " + StringUtil.simpleClassName(SctpMessage.class));
}
@Override
public ChannelFuture bindAddress(InetAddress localAddress) {
return bindAddress(localAddress, newPromise());
}
@Override
public ChannelFuture bindAddress(final InetAddress localAddress, final ChannelPromise promise) {
if (eventLoop().inEventLoop()) {
try {
javaChannel().bindAddress(localAddress);
promise.setSuccess();
} catch (Throwable t) {
promise.setFailure(t);
}
} else {
eventLoop().execute(new Runnable() {
@Override
public void run() {
bindAddress(localAddress, promise);
}
});
}
return promise;
}
@Override
public ChannelFuture unbindAddress(InetAddress localAddress) {
return unbindAddress(localAddress, newPromise());
}
@Override
public ChannelFuture unbindAddress(final InetAddress localAddress, final ChannelPromise promise) {
if (eventLoop().inEventLoop()) {
try {
javaChannel().unbindAddress(localAddress);
promise.setSuccess();
} catch (Throwable t) {
promise.setFailure(t);
}
} else {
eventLoop().execute(new Runnable() {
@Override
public void run() {
unbindAddress(localAddress, promise);
}
});
}
return promise;
}
private final class NioSctpChannelConfig extends DefaultSctpChannelConfig {
private NioSctpChannelConfig(NioSctpChannel channel, SctpChannel javaChannel) {
super(channel, javaChannel);
}
@Override
protected void autoReadCleared() {
clearReadPending();
}
}
}

@ -1,239 +0,0 @@
/*
* Copyright 2011 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.channel.sctp.nio;
import com.sun.nio.sctp.SctpChannel;
import com.sun.nio.sctp.SctpServerChannel;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelMetadata;
import io.netty.channel.ChannelOutboundBuffer;
import io.netty.channel.ChannelPromise;
import io.netty.channel.nio.AbstractNioMessageChannel;
import io.netty.channel.sctp.DefaultSctpServerChannelConfig;
import io.netty.channel.sctp.SctpServerChannelConfig;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.channels.SelectionKey;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/**
* {@link io.netty.channel.sctp.SctpServerChannel} implementation which use non-blocking mode to accept new
* connections and create the {@link NioSctpChannel} for them.
*
* Be aware that not all operations systems support SCTP. Please refer to the documentation of your operation system,
* to understand what you need to do to use it. Also this feature is only supported on Java 7+.
*/
public class NioSctpServerChannel extends AbstractNioMessageChannel
implements io.netty.channel.sctp.SctpServerChannel {
private static final ChannelMetadata METADATA = new ChannelMetadata(false, 16);
private static SctpServerChannel newSocket() {
try {
return SctpServerChannel.open();
} catch (IOException e) {
throw new ChannelException(
"Failed to open a server socket.", e);
}
}
private final SctpServerChannelConfig config;
/**
* Create a new instance
*/
public NioSctpServerChannel() {
super(null, newSocket(), SelectionKey.OP_ACCEPT);
config = new NioSctpServerChannelConfig(this, javaChannel());
}
@Override
public ChannelMetadata metadata() {
return METADATA;
}
@Override
public Set<InetSocketAddress> allLocalAddresses() {
try {
final Set<SocketAddress> allLocalAddresses = javaChannel().getAllLocalAddresses();
final Set<InetSocketAddress> addresses = new LinkedHashSet<InetSocketAddress>(allLocalAddresses.size());
for (SocketAddress socketAddress : allLocalAddresses) {
addresses.add((InetSocketAddress) socketAddress);
}
return addresses;
} catch (Throwable ignored) {
return Collections.emptySet();
}
}
@Override
public SctpServerChannelConfig config() {
return config;
}
@Override
public boolean isActive() {
return isOpen() && !allLocalAddresses().isEmpty();
}
@Override
public InetSocketAddress remoteAddress() {
return null;
}
@Override
public InetSocketAddress localAddress() {
return (InetSocketAddress) super.localAddress();
}
@Override
protected SctpServerChannel javaChannel() {
return (SctpServerChannel) super.javaChannel();
}
@Override
protected SocketAddress localAddress0() {
try {
Iterator<SocketAddress> i = javaChannel().getAllLocalAddresses().iterator();
if (i.hasNext()) {
return i.next();
}
} catch (IOException e) {
// ignore
}
return null;
}
@Override
protected void doBind(SocketAddress localAddress) throws Exception {
javaChannel().bind(localAddress, config.getBacklog());
}
@Override
protected void doClose() throws Exception {
javaChannel().close();
}
@Override
protected int doReadMessages(List<Object> buf) throws Exception {
SctpChannel ch = javaChannel().accept();
if (ch == null) {
return 0;
}
buf.add(new NioSctpChannel(this, ch));
return 1;
}
@Override
public ChannelFuture bindAddress(InetAddress localAddress) {
return bindAddress(localAddress, newPromise());
}
@Override
public ChannelFuture bindAddress(final InetAddress localAddress, final ChannelPromise promise) {
if (eventLoop().inEventLoop()) {
try {
javaChannel().bindAddress(localAddress);
promise.setSuccess();
} catch (Throwable t) {
promise.setFailure(t);
}
} else {
eventLoop().execute(new Runnable() {
@Override
public void run() {
bindAddress(localAddress, promise);
}
});
}
return promise;
}
@Override
public ChannelFuture unbindAddress(InetAddress localAddress) {
return unbindAddress(localAddress, newPromise());
}
@Override
public ChannelFuture unbindAddress(final InetAddress localAddress, final ChannelPromise promise) {
if (eventLoop().inEventLoop()) {
try {
javaChannel().unbindAddress(localAddress);
promise.setSuccess();
} catch (Throwable t) {
promise.setFailure(t);
}
} else {
eventLoop().execute(new Runnable() {
@Override
public void run() {
unbindAddress(localAddress, promise);
}
});
}
return promise;
}
// Unnecessary stuff
@Override
protected boolean doConnect(
SocketAddress remoteAddress, SocketAddress localAddress) throws Exception {
throw new UnsupportedOperationException();
}
@Override
protected void doFinishConnect() throws Exception {
throw new UnsupportedOperationException();
}
@Override
protected SocketAddress remoteAddress0() {
return null;
}
@Override
protected void doDisconnect() throws Exception {
throw new UnsupportedOperationException();
}
@Override
protected boolean doWriteMessage(Object msg, ChannelOutboundBuffer in) throws Exception {
throw new UnsupportedOperationException();
}
@Override
protected Object filterOutboundMessage(Object msg) throws Exception {
throw new UnsupportedOperationException();
}
private final class NioSctpServerChannelConfig extends DefaultSctpServerChannelConfig {
private NioSctpServerChannelConfig(NioSctpServerChannel channel, SctpServerChannel javaChannel) {
super(channel, javaChannel);
}
@Override
protected void autoReadCleared() {
clearReadPending();
}
}
}

@ -1,21 +0,0 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* <a href="https://en.wikipedia.org/wiki/New_I/O">NIO</a>-based SCTP Channel
* API implementation - recommended for a large number of connections (&gt;= 1000).
*/
package io.netty.channel.sctp.nio;

@ -1,474 +0,0 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.channel.sctp.oio;
import com.sun.nio.sctp.Association;
import com.sun.nio.sctp.MessageInfo;
import com.sun.nio.sctp.NotificationHandler;
import com.sun.nio.sctp.SctpChannel;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelMetadata;
import io.netty.channel.ChannelOutboundBuffer;
import io.netty.channel.ChannelPromise;
import io.netty.channel.RecvByteBufAllocator;
import io.netty.channel.oio.AbstractOioMessageChannel;
import io.netty.channel.sctp.DefaultSctpChannelConfig;
import io.netty.channel.sctp.SctpChannelConfig;
import io.netty.channel.sctp.SctpMessage;
import io.netty.channel.sctp.SctpNotificationHandler;
import io.netty.channel.sctp.SctpServerChannel;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.StringUtil;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/**
* {@link io.netty.channel.sctp.SctpChannel} implementation which use blocking mode and allows to read / write
* {@link SctpMessage}s to the underlying {@link SctpChannel}.
*
* Be aware that not all operations systems support SCTP. Please refer to the documentation of your operation system,
* to understand what you need to do to use it. Also this feature is only supported on Java 7+.
*
* @deprecated use {@link io.netty.channel.sctp.nio.NioSctpChannel}.
*/
@Deprecated
public class OioSctpChannel extends AbstractOioMessageChannel
implements io.netty.channel.sctp.SctpChannel {
private static final InternalLogger logger =
InternalLoggerFactory.getInstance(OioSctpChannel.class);
private static final ChannelMetadata METADATA = new ChannelMetadata(false);
private static final String EXPECTED_TYPE = " (expected: " + StringUtil.simpleClassName(SctpMessage.class) + ')';
private final SctpChannel ch;
private final SctpChannelConfig config;
private final Selector readSelector;
private final Selector writeSelector;
private final Selector connectSelector;
private final NotificationHandler<?> notificationHandler;
private static SctpChannel openChannel() {
try {
return SctpChannel.open();
} catch (IOException e) {
throw new ChannelException("Failed to open a sctp channel.", e);
}
}
/**
* Create a new instance with an new {@link SctpChannel}.
*/
public OioSctpChannel() {
this(openChannel());
}
/**
* Create a new instance from the given {@link SctpChannel}.
*
* @param ch the {@link SctpChannel} which is used by this instance
*/
public OioSctpChannel(SctpChannel ch) {
this(null, ch);
}
/**
* Create a new instance from the given {@link SctpChannel}.
*
* @param parent the parent {@link Channel} which was used to create this instance. This can be null if the
* {@link} has no parent as it was created by your self.
* @param ch the {@link SctpChannel} which is used by this instance
*/
public OioSctpChannel(Channel parent, SctpChannel ch) {
super(parent);
this.ch = ch;
boolean success = false;
try {
ch.configureBlocking(false);
readSelector = Selector.open();
writeSelector = Selector.open();
connectSelector = Selector.open();
ch.register(readSelector, SelectionKey.OP_READ);
ch.register(writeSelector, SelectionKey.OP_WRITE);
ch.register(connectSelector, SelectionKey.OP_CONNECT);
config = new OioSctpChannelConfig(this, ch);
notificationHandler = new SctpNotificationHandler(this);
success = true;
} catch (Exception e) {
throw new ChannelException("failed to initialize a sctp channel", e);
} finally {
if (!success) {
try {
ch.close();
} catch (IOException e) {
logger.warn("Failed to close a sctp channel.", e);
}
}
}
}
@Override
public InetSocketAddress localAddress() {
return (InetSocketAddress) super.localAddress();
}
@Override
public InetSocketAddress remoteAddress() {
return (InetSocketAddress) super.remoteAddress();
}
@Override
public SctpServerChannel parent() {
return (SctpServerChannel) super.parent();
}
@Override
public ChannelMetadata metadata() {
return METADATA;
}
@Override
public SctpChannelConfig config() {
return config;
}
@Override
public boolean isOpen() {
return ch.isOpen();
}
@Override
protected int doReadMessages(List<Object> msgs) throws Exception {
if (!readSelector.isOpen()) {
return 0;
}
int readMessages = 0;
final int selectedKeys = readSelector.select(SO_TIMEOUT);
final boolean keysSelected = selectedKeys > 0;
if (!keysSelected) {
return readMessages;
}
// We must clear the selectedKeys because the Selector will never do it. If we do not clear it, the selectionKey
// will always be returned even if there is no data can be read which causes performance issue. And in some
// implementation of Selector, the select method may return 0 if the selectionKey which is ready for process has
// already been in the selectedKeys and cause the keysSelected above to be false even if we actually have
// something to read.
readSelector.selectedKeys().clear();
final RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();
ByteBuf buffer = allocHandle.allocate(config().getAllocator());
boolean free = true;
try {
ByteBuffer data = buffer.nioBuffer(buffer.writerIndex(), buffer.writableBytes());
MessageInfo messageInfo = ch.receive(data, null, notificationHandler);
if (messageInfo == null) {
return readMessages;
}
data.flip();
allocHandle.lastBytesRead(data.remaining());
msgs.add(new SctpMessage(messageInfo,
buffer.writerIndex(buffer.writerIndex() + allocHandle.lastBytesRead())));
free = false;
++readMessages;
} catch (Throwable cause) {
PlatformDependent.throwException(cause);
} finally {
if (free) {
buffer.release();
}
}
return readMessages;
}
@Override
protected void doWrite(ChannelOutboundBuffer in) throws Exception {
if (!writeSelector.isOpen()) {
return;
}
final int size = in.size();
final int selectedKeys = writeSelector.select(SO_TIMEOUT);
if (selectedKeys > 0) {
final Set<SelectionKey> writableKeys = writeSelector.selectedKeys();
if (writableKeys.isEmpty()) {
return;
}
Iterator<SelectionKey> writableKeysIt = writableKeys.iterator();
int written = 0;
for (;;) {
if (written == size) {
// all written
return;
}
writableKeysIt.next();
writableKeysIt.remove();
SctpMessage packet = (SctpMessage) in.current();
if (packet == null) {
return;
}
ByteBuf data = packet.content();
int dataLen = data.readableBytes();
ByteBuffer nioData;
if (data.nioBufferCount() != -1) {
nioData = data.nioBuffer();
} else {
nioData = ByteBuffer.allocate(dataLen);
data.getBytes(data.readerIndex(), nioData);
nioData.flip();
}
final MessageInfo mi = MessageInfo.createOutgoing(association(), null, packet.streamIdentifier());
mi.payloadProtocolID(packet.protocolIdentifier());
mi.streamNumber(packet.streamIdentifier());
mi.unordered(packet.isUnordered());
ch.send(nioData, mi);
written ++;
in.remove();
if (!writableKeysIt.hasNext()) {
return;
}
}
}
}
@Override
protected Object filterOutboundMessage(Object msg) throws Exception {
if (msg instanceof SctpMessage) {
return msg;
}
throw new UnsupportedOperationException(
"unsupported message type: " + StringUtil.simpleClassName(msg) + EXPECTED_TYPE);
}
@Override
public Association association() {
try {
return ch.association();
} catch (IOException ignored) {
return null;
}
}
@Override
public boolean isActive() {
return isOpen() && association() != null;
}
@Override
protected SocketAddress localAddress0() {
try {
Iterator<SocketAddress> i = ch.getAllLocalAddresses().iterator();
if (i.hasNext()) {
return i.next();
}
} catch (IOException e) {
// ignore
}
return null;
}
@Override
public Set<InetSocketAddress> allLocalAddresses() {
try {
final Set<SocketAddress> allLocalAddresses = ch.getAllLocalAddresses();
final Set<InetSocketAddress> addresses = new LinkedHashSet<InetSocketAddress>(allLocalAddresses.size());
for (SocketAddress socketAddress : allLocalAddresses) {
addresses.add((InetSocketAddress) socketAddress);
}
return addresses;
} catch (Throwable ignored) {
return Collections.emptySet();
}
}
@Override
protected SocketAddress remoteAddress0() {
try {
Iterator<SocketAddress> i = ch.getRemoteAddresses().iterator();
if (i.hasNext()) {
return i.next();
}
} catch (IOException e) {
// ignore
}
return null;
}
@Override
public Set<InetSocketAddress> allRemoteAddresses() {
try {
final Set<SocketAddress> allLocalAddresses = ch.getRemoteAddresses();
final Set<InetSocketAddress> addresses = new LinkedHashSet<InetSocketAddress>(allLocalAddresses.size());
for (SocketAddress socketAddress : allLocalAddresses) {
addresses.add((InetSocketAddress) socketAddress);
}
return addresses;
} catch (Throwable ignored) {
return Collections.emptySet();
}
}
@Override
protected void doBind(SocketAddress localAddress) throws Exception {
ch.bind(localAddress);
}
@Override
protected void doConnect(SocketAddress remoteAddress,
SocketAddress localAddress) throws Exception {
if (localAddress != null) {
ch.bind(localAddress);
}
boolean success = false;
try {
ch.connect(remoteAddress);
boolean finishConnect = false;
while (!finishConnect) {
if (connectSelector.select(SO_TIMEOUT) >= 0) {
final Set<SelectionKey> selectionKeys = connectSelector.selectedKeys();
for (SelectionKey key : selectionKeys) {
if (key.isConnectable()) {
selectionKeys.clear();
finishConnect = true;
break;
}
}
selectionKeys.clear();
}
}
success = ch.finishConnect();
} finally {
if (!success) {
doClose();
}
}
}
@Override
protected void doDisconnect() throws Exception {
doClose();
}
@Override
protected void doClose() throws Exception {
closeSelector("read", readSelector);
closeSelector("write", writeSelector);
closeSelector("connect", connectSelector);
ch.close();
}
private static void closeSelector(String selectorName, Selector selector) {
try {
selector.close();
} catch (IOException e) {
if (logger.isWarnEnabled()) {
logger.warn("Failed to close a " + selectorName + " selector.", e);
}
}
}
@Override
public ChannelFuture bindAddress(InetAddress localAddress) {
return bindAddress(localAddress, newPromise());
}
@Override
public ChannelFuture bindAddress(final InetAddress localAddress, final ChannelPromise promise) {
if (eventLoop().inEventLoop()) {
try {
ch.bindAddress(localAddress);
promise.setSuccess();
} catch (Throwable t) {
promise.setFailure(t);
}
} else {
eventLoop().execute(new Runnable() {
@Override
public void run() {
bindAddress(localAddress, promise);
}
});
}
return promise;
}
@Override
public ChannelFuture unbindAddress(InetAddress localAddress) {
return unbindAddress(localAddress, newPromise());
}
@Override
public ChannelFuture unbindAddress(final InetAddress localAddress, final ChannelPromise promise) {
if (eventLoop().inEventLoop()) {
try {
ch.unbindAddress(localAddress);
promise.setSuccess();
} catch (Throwable t) {
promise.setFailure(t);
}
} else {
eventLoop().execute(new Runnable() {
@Override
public void run() {
unbindAddress(localAddress, promise);
}
});
}
return promise;
}
private final class OioSctpChannelConfig extends DefaultSctpChannelConfig {
private OioSctpChannelConfig(OioSctpChannel channel, SctpChannel javaChannel) {
super(channel, javaChannel);
}
@Override
protected void autoReadCleared() {
clearReadPending();
}
}
}

@ -1,308 +0,0 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.channel.sctp.oio;
import com.sun.nio.sctp.SctpChannel;
import com.sun.nio.sctp.SctpServerChannel;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelMetadata;
import io.netty.channel.ChannelOutboundBuffer;
import io.netty.channel.ChannelPromise;
import io.netty.channel.oio.AbstractOioMessageChannel;
import io.netty.channel.sctp.DefaultSctpServerChannelConfig;
import io.netty.channel.sctp.SctpServerChannelConfig;
import io.netty.util.internal.ObjectUtil;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/**
* {@link io.netty.channel.sctp.SctpServerChannel} implementation which use blocking mode to accept new
* connections and create the {@link OioSctpChannel} for them.
*
* Be aware that not all operations systems support SCTP. Please refer to the documentation of your operation system,
* to understand what you need to do to use it. Also this feature is only supported on Java 7+.
*
* @deprecated use {@link io.netty.channel.sctp.nio.NioSctpServerChannel}.
*/
@Deprecated
public class OioSctpServerChannel extends AbstractOioMessageChannel
implements io.netty.channel.sctp.SctpServerChannel {
private static final InternalLogger logger =
InternalLoggerFactory.getInstance(OioSctpServerChannel.class);
private static final ChannelMetadata METADATA = new ChannelMetadata(false, 1);
private static SctpServerChannel newServerSocket() {
try {
return SctpServerChannel.open();
} catch (IOException e) {
throw new ChannelException("failed to create a sctp server channel", e);
}
}
private final SctpServerChannel sch;
private final SctpServerChannelConfig config;
private final Selector selector;
/**
* Create a new instance with an new {@link SctpServerChannel}
*/
public OioSctpServerChannel() {
this(newServerSocket());
}
/**
* Create a new instance from the given {@link SctpServerChannel}
*
* @param sch the {@link SctpServerChannel} which is used by this instance
*/
public OioSctpServerChannel(SctpServerChannel sch) {
super(null);
this.sch = ObjectUtil.checkNotNull(sch, "sctp server channel");
boolean success = false;
try {
sch.configureBlocking(false);
selector = Selector.open();
sch.register(selector, SelectionKey.OP_ACCEPT);
config = new OioSctpServerChannelConfig(this, sch);
success = true;
} catch (Exception e) {
throw new ChannelException("failed to initialize a sctp server channel", e);
} finally {
if (!success) {
try {
sch.close();
} catch (IOException e) {
logger.warn("Failed to close a sctp server channel.", e);
}
}
}
}
@Override
public ChannelMetadata metadata() {
return METADATA;
}
@Override
public SctpServerChannelConfig config() {
return config;
}
@Override
public InetSocketAddress remoteAddress() {
return null;
}
@Override
public InetSocketAddress localAddress() {
return (InetSocketAddress) super.localAddress();
}
@Override
public boolean isOpen() {
return sch.isOpen();
}
@Override
protected SocketAddress localAddress0() {
try {
Iterator<SocketAddress> i = sch.getAllLocalAddresses().iterator();
if (i.hasNext()) {
return i.next();
}
} catch (IOException e) {
// ignore
}
return null;
}
@Override
public Set<InetSocketAddress> allLocalAddresses() {
try {
final Set<SocketAddress> allLocalAddresses = sch.getAllLocalAddresses();
final Set<InetSocketAddress> addresses = new LinkedHashSet<InetSocketAddress>(allLocalAddresses.size());
for (SocketAddress socketAddress : allLocalAddresses) {
addresses.add((InetSocketAddress) socketAddress);
}
return addresses;
} catch (Throwable ignored) {
return Collections.emptySet();
}
}
@Override
public boolean isActive() {
return isOpen() && localAddress0() != null;
}
@Override
protected void doBind(SocketAddress localAddress) throws Exception {
sch.bind(localAddress, config.getBacklog());
}
@Override
protected void doClose() throws Exception {
try {
selector.close();
} catch (IOException e) {
logger.warn("Failed to close a selector.", e);
}
sch.close();
}
@Override
protected int doReadMessages(List<Object> buf) throws Exception {
if (!isActive()) {
return -1;
}
SctpChannel s = null;
int acceptedChannels = 0;
try {
final int selectedKeys = selector.select(SO_TIMEOUT);
if (selectedKeys > 0) {
final Iterator<SelectionKey> selectionKeys = selector.selectedKeys().iterator();
for (;;) {
SelectionKey key = selectionKeys.next();
selectionKeys.remove();
if (key.isAcceptable()) {
s = sch.accept();
if (s != null) {
buf.add(new OioSctpChannel(this, s));
acceptedChannels ++;
}
}
if (!selectionKeys.hasNext()) {
return acceptedChannels;
}
}
}
} catch (Throwable t) {
logger.warn("Failed to create a new channel from an accepted sctp channel.", t);
if (s != null) {
try {
s.close();
} catch (Throwable t2) {
logger.warn("Failed to close a sctp channel.", t2);
}
}
}
return acceptedChannels;
}
@Override
public ChannelFuture bindAddress(InetAddress localAddress) {
return bindAddress(localAddress, newPromise());
}
@Override
public ChannelFuture bindAddress(final InetAddress localAddress, final ChannelPromise promise) {
if (eventLoop().inEventLoop()) {
try {
sch.bindAddress(localAddress);
promise.setSuccess();
} catch (Throwable t) {
promise.setFailure(t);
}
} else {
eventLoop().execute(new Runnable() {
@Override
public void run() {
bindAddress(localAddress, promise);
}
});
}
return promise;
}
@Override
public ChannelFuture unbindAddress(InetAddress localAddress) {
return unbindAddress(localAddress, newPromise());
}
@Override
public ChannelFuture unbindAddress(final InetAddress localAddress, final ChannelPromise promise) {
if (eventLoop().inEventLoop()) {
try {
sch.unbindAddress(localAddress);
promise.setSuccess();
} catch (Throwable t) {
promise.setFailure(t);
}
} else {
eventLoop().execute(new Runnable() {
@Override
public void run() {
unbindAddress(localAddress, promise);
}
});
}
return promise;
}
@Override
protected void doConnect(
SocketAddress remoteAddress, SocketAddress localAddress) throws Exception {
throw new UnsupportedOperationException();
}
@Override
protected SocketAddress remoteAddress0() {
return null;
}
@Override
protected void doDisconnect() throws Exception {
throw new UnsupportedOperationException();
}
@Override
protected void doWrite(ChannelOutboundBuffer in) throws Exception {
throw new UnsupportedOperationException();
}
@Override
protected Object filterOutboundMessage(Object msg) throws Exception {
throw new UnsupportedOperationException();
}
private final class OioSctpServerChannelConfig extends DefaultSctpServerChannelConfig {
private OioSctpServerChannelConfig(OioSctpServerChannel channel, SctpServerChannel javaChannel) {
super(channel, javaChannel);
}
@Override
protected void autoReadCleared() {
clearReadPending();
}
}
}

@ -1,23 +0,0 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* Old blocking I/O based SCTP channel API implementation - recommended for
* a small number of connections (&lt; 1000).
*
* @deprecated use NIO based SCTP implementation.
*/
package io.netty.channel.sctp.oio;

@ -1,20 +0,0 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* Abstract SCTP socket interfaces which extend the core channel API.
*/
package io.netty.channel.sctp;

@ -1,9 +0,0 @@
module org.xbib.io.netty.channel.sctp {
exports io.netty.channel.sctp;
exports io.netty.channel.sctp.nio;
exports io.netty.channel.sctp.oio;
requires org.xbib.io.netty.buffer;
requires org.xbib.io.netty.channel;
requires org.xbib.io.netty.util;
requires jdk.sctp;
}

@ -30,7 +30,7 @@ public final class UnixChannelUtil {
}
/**
* Checks if the specified buffer has memory address or is composed of n(n <= IOV_MAX) NIO direct buffers.
* Checks if the specified buffer has memory address or is composed of n(n &lt;= IOV_MAX) NIO direct buffers.
* (We check this because otherwise we need to make it a new direct buffer.)
*/
public static boolean isBufferCopyNeededForWrite(ByteBuf byteBuf) {

@ -1,246 +0,0 @@
/*
* Copyright 2022 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.nativeimage;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import io.netty.channel.ChannelHandler;
import io.netty.channel.NativeImageHandlerMetadataTest;
import org.junit.jupiter.api.Assertions;
import org.reflections.Reflections;
import org.reflections.util.ConfigurationBuilder;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Type;
import java.net.URL;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Generates native-image reflection metadata for subtypes of {@link io.netty.channel.ChannelHandler}.
* <p>
* To use, create a JUnit test in the desired Netty module and invoke {@link #generateMetadata(String...)} with a list
* of packages present in the target Netty module that may contain subtypes of the ChannelHandler.
* <p>
* See {@link NativeImageHandlerMetadataTest}
*/
public final class ChannelHandlerMetadataUtil {
@SuppressWarnings("UnstableApiUsage")
private static final Type HANDLER_METADATA_LIST_TYPE = new TypeToken<List<HandlerMetadata>>() {
}.getType();
private static final Gson gson = new GsonBuilder().setPrettyPrinting().create();
private ChannelHandlerMetadataUtil() {
}
public static void generateMetadata(String... packageNames) {
String projectGroupId = System.getProperty("nativeImage.handlerMetadataGroupId");
String projectArtifactId = System.getProperty("nativeimage.handlerMetadataArtifactId");
Set<Class<? extends ChannelHandler>> subtypes = findChannelHandlerSubclasses(packageNames);
if (Arrays.asList(packageNames).contains("io.netty.channel")) {
// We want the metadata for the ChannelHandler itself too
subtypes.add(ChannelHandler.class);
}
Set<HandlerMetadata> handlerMetadata = new HashSet<HandlerMetadata>();
for (Class<?> subtype : subtypes) {
handlerMetadata.add(new HandlerMetadata(subtype.getName(), new Condition(subtype.getName()), true));
}
String projectRelativeResourcePath = "src/main/resources/META-INF/native-image/" + projectGroupId + "/" +
projectArtifactId + "/generated/handlers/reflect-config.json";
File existingMetadataFile = new File(projectRelativeResourcePath);
String existingMetadataPath = existingMetadataFile.getAbsolutePath();
if (!existingMetadataFile.exists()) {
if (handlerMetadata.size() == 0) {
return;
}
String message = "Native Image reflection metadata is required for handlers in this project. " +
"This metadata was not found under " +
existingMetadataPath +
"\nPlease create this file with the following content: \n" +
getMetadataJsonString(handlerMetadata) +
"\n";
Assertions.fail(message);
}
List<HandlerMetadata> existingMetadata = null;
try {
FileReader reader = new FileReader(existingMetadataFile);
existingMetadata = gson.fromJson(reader, HANDLER_METADATA_LIST_TYPE);
} catch (IOException e) {
Assertions.fail("Failed to open the native-image metadata file at: " + existingMetadataPath, e);
}
Set<HandlerMetadata> newMetadata = new HashSet<HandlerMetadata>(handlerMetadata);
newMetadata.removeAll(existingMetadata);
Set<HandlerMetadata> removedMetadata = new HashSet<HandlerMetadata>(existingMetadata);
removedMetadata.removeAll(handlerMetadata);
if (!newMetadata.isEmpty() || !removedMetadata.isEmpty()) {
StringBuilder builder = new StringBuilder();
builder.append("In the native-image handler metadata file at ")
.append(existingMetadataPath)
.append("\n");
if (!newMetadata.isEmpty()) {
builder.append("The following new metadata must be added:\n\n")
.append(getMetadataJsonString(newMetadata))
.append("\n\n");
}
if (!removedMetadata.isEmpty()) {
builder.append("The following metadata must be removed:\n\n")
.append(getMetadataJsonString(removedMetadata))
.append("\n\n");
}
builder.append("Expected metadata file contents:\n\n")
.append(getMetadataJsonString(handlerMetadata))
.append("\n");
Assertions.fail(builder.toString());
}
}
private static Set<Class<? extends ChannelHandler>> findChannelHandlerSubclasses(String... packageNames) {
Reflections reflections = new Reflections(
new ConfigurationBuilder()
.forPackages(packageNames));
Set<Class<? extends ChannelHandler>> allSubtypes = reflections.getSubTypesOf(ChannelHandler.class);
Set<Class<? extends ChannelHandler>> targetSubtypes = new HashSet<Class<? extends ChannelHandler>>();
for (Class<? extends ChannelHandler> subtype : allSubtypes) {
if (isTestClass(subtype)) {
continue;
}
String className = subtype.getName();
boolean shouldInclude = false;
for (String packageName : packageNames) {
if (className.startsWith(packageName)) {
shouldInclude = true;
break;
}
}
if (shouldInclude) {
targetSubtypes.add(subtype);
}
}
return targetSubtypes;
}
private static boolean isTestClass(Class<? extends ChannelHandler> clazz) {
String[] parts = clazz.getName().split("\\.");
if (parts.length > 0) {
URL classFile = clazz.getResource(parts[parts.length - 1] + ".class");
if (classFile != null) {
return classFile.toString().contains("Test");
}
}
return false;
}
private static String getMetadataJsonString(Set<HandlerMetadata> metadata) {
List<HandlerMetadata> metadataList = new ArrayList<HandlerMetadata>(metadata);
Collections.sort(metadataList, new Comparator<HandlerMetadata>() {
@Override
public int compare(HandlerMetadata h1, HandlerMetadata h2) {
return Collator.getInstance().compare(h1.name, h2.name);
}
});
return gson.toJson(metadataList, HANDLER_METADATA_LIST_TYPE);
}
private static final class Condition {
Condition(String typeReachable) {
this.typeReachable = typeReachable;
}
final String typeReachable;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Condition condition = (Condition) o;
return typeReachable != null && typeReachable.equals(condition.typeReachable);
}
@Override
public int hashCode() {
return typeReachable.hashCode();
}
}
private static final class HandlerMetadata {
final String name;
final Condition condition;
final boolean queryAllPublicMethods;
HandlerMetadata(String name, Condition condition, boolean queryAllPublicMethods) {
this.name = name;
this.condition = condition;
this.queryAllPublicMethods = queryAllPublicMethods;
}
@Override
public String toString() {
return name;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
HandlerMetadata that = (HandlerMetadata) o;
return queryAllPublicMethods == that.queryAllPublicMethods
&& (name != null && name.equals(that.name))
&& (condition != null && condition.equals(that.condition));
}
@Override
public int hashCode() {
return name.hashCode();
}
}
}

@ -1,4 +0,0 @@
dependencies {
api project(':netty-channel-sctp')
api project(':netty-handler-codec')
}

@ -1,64 +0,0 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.handler.codec.sctp;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.sctp.SctpMessage;
import io.netty.handler.codec.CodecException;
import io.netty.handler.codec.MessageToMessageDecoder;
import java.util.List;
/**
* A ChannelHandler which receives {@link SctpMessage}s which belong to a application protocol form a specific
* SCTP Stream and decode it as {@link ByteBuf}.
*/
public class SctpInboundByteStreamHandler extends MessageToMessageDecoder<SctpMessage> {
private final int protocolIdentifier;
private final int streamIdentifier;
/**
* @param streamIdentifier accepted stream number, this should be >=0 or &lt;= max stream number of the association.
* @param protocolIdentifier supported application protocol.
*/
public SctpInboundByteStreamHandler(int protocolIdentifier, int streamIdentifier) {
this.protocolIdentifier = protocolIdentifier;
this.streamIdentifier = streamIdentifier;
}
@Override
public final boolean acceptInboundMessage(Object msg) throws Exception {
if (super.acceptInboundMessage(msg)) {
return acceptInboundMessage((SctpMessage) msg);
}
return false;
}
protected boolean acceptInboundMessage(SctpMessage msg) {
return msg.protocolIdentifier() == protocolIdentifier && msg.streamIdentifier() == streamIdentifier;
}
@Override
protected void decode(ChannelHandlerContext ctx, SctpMessage msg, List<Object> out) throws Exception {
if (!msg.isComplete()) {
throw new CodecException(String.format("Received SctpMessage is not complete, please add %s in the " +
"pipeline before this handler", SctpMessageCompletionHandler.class.getSimpleName()));
}
out.add(msg.content().retain());
}
}

@ -1,80 +0,0 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.handler.codec.sctp;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandler;
import io.netty.channel.sctp.SctpMessage;
import io.netty.handler.codec.MessageToMessageDecoder;
import io.netty.util.collection.IntObjectHashMap;
import io.netty.util.collection.IntObjectMap;
import java.util.List;
/**
* {@link MessageToMessageDecoder} which will take care of handle fragmented {@link SctpMessage}s, so
* only <strong>complete</strong> {@link SctpMessage}s will be forwarded to the next
* {@link ChannelInboundHandler}.
*/
public class SctpMessageCompletionHandler extends MessageToMessageDecoder<SctpMessage> {
private final IntObjectMap<ByteBuf> fragments = new IntObjectHashMap<ByteBuf>();
@Override
protected void decode(ChannelHandlerContext ctx, SctpMessage msg, List<Object> out) throws Exception {
final ByteBuf byteBuf = msg.content();
final int protocolIdentifier = msg.protocolIdentifier();
final int streamIdentifier = msg.streamIdentifier();
final boolean isComplete = msg.isComplete();
final boolean isUnordered = msg.isUnordered();
ByteBuf frag = fragments.remove(streamIdentifier);
if (frag == null) {
frag = Unpooled.EMPTY_BUFFER;
}
if (isComplete && !frag.isReadable()) {
//data chunk is not fragmented
out.add(msg);
} else if (!isComplete && frag.isReadable()) {
//more message to complete
fragments.put(streamIdentifier, Unpooled.wrappedBuffer(frag, byteBuf));
} else if (isComplete && frag.isReadable()) {
//last message to complete
SctpMessage assembledMsg = new SctpMessage(
protocolIdentifier,
streamIdentifier,
isUnordered,
Unpooled.wrappedBuffer(frag, byteBuf));
out.add(assembledMsg);
} else {
//first incomplete message
fragments.put(streamIdentifier, byteBuf);
}
byteBuf.retain();
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
for (ByteBuf buffer: fragments.values()) {
buffer.release();
}
fragments.clear();
super.handlerRemoved(ctx);
}
}

@ -1,39 +0,0 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.handler.codec.sctp;
import io.netty.channel.sctp.SctpMessage;
import io.netty.handler.codec.CodecException;
import io.netty.handler.codec.MessageToMessageDecoder;
public abstract class SctpMessageToMessageDecoder extends MessageToMessageDecoder<SctpMessage> {
@Override
public boolean acceptInboundMessage(Object msg) throws Exception {
if (msg instanceof SctpMessage) {
SctpMessage sctpMsg = (SctpMessage) msg;
if (sctpMsg.isComplete()) {
return true;
}
throw new CodecException(String.format("Received SctpMessage is not complete, please add %s in " +
"the pipeline before this handler", SctpMessageCompletionHandler.class.getSimpleName()));
} else {
return false;
}
}
}

@ -1,58 +0,0 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.handler.codec.sctp;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.sctp.SctpMessage;
import io.netty.handler.codec.MessageToMessageEncoder;
import java.util.List;
/**
* A ChannelHandler which transform {@link ByteBuf} to {@link SctpMessage} and send it through a specific stream
* with given protocol identifier.
* Unordered delivery of all messages may be requested by passing unordered = true to the constructor.
*/
public class SctpOutboundByteStreamHandler extends MessageToMessageEncoder<ByteBuf> {
private final int streamIdentifier;
private final int protocolIdentifier;
private final boolean unordered;
/**
* @param streamIdentifier stream number, this should be >=0 or &lt;= max stream number of the association.
* @param protocolIdentifier supported application protocol id.
*/
public SctpOutboundByteStreamHandler(int streamIdentifier, int protocolIdentifier) {
this(streamIdentifier, protocolIdentifier, false);
}
/**
* @param streamIdentifier stream number, this should be >=0 or &lt;= max stream number of the association.
* @param protocolIdentifier supported application protocol id.
* @param unordered if {@literal true}, SCTP Data Chunks will be sent with the U (unordered) flag set.
*/
public SctpOutboundByteStreamHandler(int streamIdentifier, int protocolIdentifier, boolean unordered) {
this.streamIdentifier = streamIdentifier;
this.protocolIdentifier = protocolIdentifier;
this.unordered = unordered;
}
@Override
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
out.add(new SctpMessage(protocolIdentifier, streamIdentifier, unordered, msg.retain()));
}
}

@ -1,20 +0,0 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* Decoder and encoders to manage message completion and multi-streaming codec in SCTP/IP.
*/
package io.netty.handler.codec.sctp;

@ -1,8 +0,0 @@
module org.xbib.io.netty.handler.codec.sctp {
exports io.netty.handler.codec.sctp;
requires org.xbib.io.netty.buffer;
requires org.xbib.io.netty.channel;
requires org.xbib.io.netty.channel.sctp;
requires org.xbib.io.netty.handler.codec;
requires org.xbib.io.netty.util;
}

@ -67,7 +67,7 @@ import static java.lang.Integer.MAX_VALUE;
* <h3>Pitfalls</h3>
* <p>
* Be aware that sub-classes of {@link ByteToMessageDecoder} <strong>MUST NOT</strong>
* annotated with {@link @Sharable}.
* annotated with {@code @Sharable}.
* <p>
* Some methods such as {@link ByteBuf#readBytes(int)} will cause a memory leak if the returned buffer
* is not released or added to the <tt>out</tt> {@link List}. Use derived buffers like {@link ByteBuf#readSlice(int)}

@ -137,7 +137,7 @@ public abstract class MessageAggregator<I, S, C extends ByteBufHolder, O extends
* </pre>
* or with {@code instanceof} and boolean field check:
* <pre>
* return msg instanceof MyContentMessage && msg.isLastFragment();
* return msg instanceof MyContentMessage &amp;&amp; msg.isLastFragment();
* </pre>
*/
protected abstract boolean isLastContentMessage(C msg) throws Exception;

@ -34,12 +34,12 @@ import java.util.List;
* <p>
* The byte stream is expected to be in UTF-8 character encoding or ASCII. The current implementation
* uses direct {@code byte} to {@code char} cast and then compares that {@code char} to a few low range
* ASCII characters like {@code '{'}, {@code '['} or {@code '"'}. UTF-8 is not using low range [0..0x7F]
* ASCII characters like {@code '&#7b;'}, {@code '['} or {@code '"'}. UTF-8 is not using low range [0..0x7F]
* byte values for multibyte codepoint representations therefore fully supported by this implementation.
* <p>
* This class does not do any real parsing or validation. A sequence of bytes is considered a JSON object/array
* if it contains a matching number of opening and closing braces/brackets. It's up to a subsequent
* {@link ChannelHandler} to parse the JSON text into a more usable form i.e. a POJO.
* {@link io.netty.channel.ChannelHandler} to parse the JSON text into a more usable form i.e. a POJO.
*/
public class JsonObjectDecoder extends ByteToMessageDecoder {

@ -25,8 +25,5 @@
* <tt>jdk.serialFilter</tt> system property, for instance.
* See the <a href="https://docs.oracle.com/en/java/javase/17/core/serialization-filtering1.html">
* serialization filtering</a> article for more information.
*
* @deprecated This package has been deprecated with no replacement,
* because serialization can be a security liability
*/
package io.netty.handler.codec.serialization;

@ -838,7 +838,7 @@ public final class SSL {
/**
* Extracts the random value sent from the server to the client during the initial SSL/TLS handshake.
* This is needed to extract the HMAC & keys from the master key according to the TLS PRF.
* This is needed to extract the HMAC &amp; keys from the master key according to the TLS PRF.
* <b>This is not a random number generator.</b>
*
* @param ssl the SSL instance (SSL *)
@ -848,7 +848,7 @@ public final class SSL {
/**
* Extracts the random value sent from the client to the server during the initial SSL/TLS handshake.
* This is needed to extract the HMAC & keys from the master key according to the TLS PRF.
* This is needed to extract the HMAC &amp; keys from the master key according to the TLS PRF.
* <b>This is not a random number generator.</b>
*
* @param ssl the SSL instance (SSL *)

@ -43,7 +43,7 @@ public interface SSLSessionCache {
*
* @param sslCtx {code SSL_CTX*}
* @param sessionId the session id
* @return the {@link SSL_SESSION} or {@code -1} if none was found in the cache.
* @return the {@code SSL_SESSION} or {@code -1} if none was found in the cache.
*/
long getSession(long sslCtx, byte[] sessionId);
}

@ -2,8 +2,6 @@ dependencies {
api project(':netty-buffer')
api project(':netty-channel')
api project(':netty-util')
implementation project(':netty-channel-sctp')
implementation project(':netty-handler-codec-sctp')
implementation project(':netty-handler-codec-spdy')
implementation project(':netty-handler')
implementation project(':netty-handler-ssl')

@ -1,42 +0,0 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.testsuite.transport.sctp;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelOption;
import io.netty.testsuite.transport.AbstractComboTestsuiteTest;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.util.NetUtil;
import java.net.InetSocketAddress;
import java.util.List;
public abstract class AbstractSctpTest extends AbstractComboTestsuiteTest<ServerBootstrap, Bootstrap> {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return SctpTestPermutation.sctpChannel();
}
@Override
protected void configure(ServerBootstrap serverBootstrap, Bootstrap bootstrap, ByteBufAllocator allocator) {
serverBootstrap.localAddress(new InetSocketAddress(NetUtil.LOCALHOST, 0));
serverBootstrap.option(ChannelOption.ALLOCATOR, allocator);
serverBootstrap.childOption(ChannelOption.ALLOCATOR, allocator);
bootstrap.option(ChannelOption.ALLOCATOR, allocator);
}
}

@ -1,188 +0,0 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.testsuite.transport.sctp;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.sctp.SctpChannel;
import io.netty.handler.codec.sctp.SctpInboundByteStreamHandler;
import io.netty.handler.codec.sctp.SctpMessageCompletionHandler;
import io.netty.handler.codec.sctp.SctpOutboundByteStreamHandler;
import io.netty.testsuite.util.TestUtils;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.jupiter.api.TestInfo;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
public class SctpEchoTest extends AbstractSctpTest {
private static final Random random = new Random();
static final byte[] data = new byte[4096]; //could not test ultra jumbo frames
static {
random.nextBytes(data);
}
@Test
public void testSimpleEcho(TestInfo testInfo) throws Throwable {
assumeTrue(TestUtils.isSctpSupported());
run(testInfo, new Runner<ServerBootstrap, Bootstrap>() {
@Override
public void run(ServerBootstrap serverBootstrap, Bootstrap bootstrap) throws Throwable {
testSimpleEcho(serverBootstrap, bootstrap);
}
});
}
public void testSimpleEcho(ServerBootstrap sb, Bootstrap cb) throws Throwable {
testSimpleEcho0(sb, cb, false);
}
@Test
public void testSimpleEchoUnordered(TestInfo testInfo) throws Throwable {
assumeTrue(TestUtils.isSctpSupported());
run(testInfo, new Runner<ServerBootstrap, Bootstrap>() {
@Override
public void run(ServerBootstrap serverBootstrap, Bootstrap bootstrap) throws Throwable {
testSimpleEchoUnordered(serverBootstrap, bootstrap);
}
});
}
public void testSimpleEchoUnordered(ServerBootstrap sb, Bootstrap cb) throws Throwable {
testSimpleEcho0(sb, cb, true);
}
private static void testSimpleEcho0(ServerBootstrap sb, Bootstrap cb, final boolean unordered) throws Throwable {
final EchoHandler sh = new EchoHandler();
final EchoHandler ch = new EchoHandler();
sb.childHandler(new ChannelInitializer<SctpChannel>() {
@Override
public void initChannel(SctpChannel c) throws Exception {
c.pipeline().addLast(
new SctpMessageCompletionHandler(),
new SctpInboundByteStreamHandler(0, 0),
new SctpOutboundByteStreamHandler(0, 0, unordered),
sh);
}
});
cb.handler(new ChannelInitializer<SctpChannel>() {
@Override
public void initChannel(SctpChannel c) throws Exception {
c.pipeline().addLast(
new SctpMessageCompletionHandler(),
new SctpInboundByteStreamHandler(0, 0),
new SctpOutboundByteStreamHandler(0, 0, unordered),
ch);
}
});
Channel sc = sb.bind().sync().channel();
Channel cc = cb.connect(sc.localAddress()).sync().channel();
for (int i = 0; i < data.length;) {
int length = Math.min(random.nextInt(1024 * 64), data.length - i);
cc.writeAndFlush(Unpooled.wrappedBuffer(data, i, length));
i += length;
}
while (ch.counter < data.length) {
if (sh.exception.get() != null) {
break;
}
if (ch.exception.get() != null) {
break;
}
Thread.sleep(50);
}
while (sh.counter < data.length) {
if (sh.exception.get() != null) {
break;
}
if (ch.exception.get() != null) {
break;
}
Thread.sleep(50);
}
sh.channel.close().sync();
ch.channel.close().sync();
sc.close().sync();
if (sh.exception.get() != null && !(sh.exception.get() instanceof IOException)) {
throw sh.exception.get();
}
if (ch.exception.get() != null && !(ch.exception.get() instanceof IOException)) {
throw ch.exception.get();
}
if (sh.exception.get() != null) {
throw sh.exception.get();
}
if (ch.exception.get() != null) {
throw ch.exception.get();
}
}
private static class EchoHandler extends SimpleChannelInboundHandler<ByteBuf> {
volatile Channel channel;
final AtomicReference<Throwable> exception = new AtomicReference<Throwable>();
volatile int counter;
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
channel = ctx.channel();
}
@Override
public void channelRead0(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
byte[] actual = new byte[in.readableBytes()];
in.readBytes(actual);
int lastIdx = counter;
for (int i = 0; i < actual.length; i++) {
assertEquals(data[i + lastIdx], actual[i]);
}
if (channel.parent() != null) {
channel.writeAndFlush(Unpooled.wrappedBuffer(actual));
}
counter += actual.length;
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (exception.compareAndSet(null, cause)) {
ctx.close();
}
}
}
}

@ -1,130 +0,0 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.testsuite.transport.sctp;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.oio.OioEventLoopGroup;
import io.netty.channel.sctp.nio.NioSctpChannel;
import io.netty.channel.sctp.nio.NioSctpServerChannel;
import io.netty.channel.sctp.oio.OioSctpChannel;
import io.netty.channel.sctp.oio.OioSctpServerChannel;
import io.netty.testsuite.util.TestUtils;
import io.netty.testsuite.transport.TestsuitePermutation.BootstrapComboFactory;
import io.netty.testsuite.transport.TestsuitePermutation.BootstrapFactory;
import io.netty.util.concurrent.DefaultThreadFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public final class SctpTestPermutation {
private static final int BOSSES = 2;
private static final int WORKERS = 3;
private static final EventLoopGroup nioBossGroup =
new NioEventLoopGroup(BOSSES, new DefaultThreadFactory("testsuite-sctp-nio-boss", true));
private static final EventLoopGroup nioWorkerGroup =
new NioEventLoopGroup(WORKERS, new DefaultThreadFactory("testsuite-sctp-nio-worker", true));
private static final EventLoopGroup oioBossGroup =
new OioEventLoopGroup(Integer.MAX_VALUE, new DefaultThreadFactory("testsuite-sctp-oio-boss", true));
private static final EventLoopGroup oioWorkerGroup =
new OioEventLoopGroup(Integer.MAX_VALUE, new DefaultThreadFactory("testsuite-sctp-oio-worker", true));
static List<BootstrapFactory<ServerBootstrap>> sctpServerChannel() {
if (!TestUtils.isSctpSupported()) {
return Collections.emptyList();
}
List<BootstrapFactory<ServerBootstrap>> list = new ArrayList<BootstrapFactory<ServerBootstrap>>();
// Make the list of ServerBootstrap factories.
list.add(new BootstrapFactory<ServerBootstrap>() {
@Override
public ServerBootstrap newInstance() {
return new ServerBootstrap().
group(nioBossGroup, nioWorkerGroup).
channel(NioSctpServerChannel.class);
}
});
list.add(new BootstrapFactory<ServerBootstrap>() {
@Override
public ServerBootstrap newInstance() {
return new ServerBootstrap().
group(oioBossGroup, oioWorkerGroup).
channel(OioSctpServerChannel.class);
}
});
return list;
}
static List<BootstrapFactory<Bootstrap>> sctpClientChannel() {
if (!TestUtils.isSctpSupported()) {
return Collections.emptyList();
}
List<BootstrapFactory<Bootstrap>> list = new ArrayList<BootstrapFactory<Bootstrap>>();
list.add(new BootstrapFactory<Bootstrap>() {
@Override
public Bootstrap newInstance() {
return new Bootstrap().group(nioWorkerGroup).channel(NioSctpChannel.class);
}
});
list.add(new BootstrapFactory<Bootstrap>() {
@Override
public Bootstrap newInstance() {
return new Bootstrap().group(oioWorkerGroup).channel(OioSctpChannel.class);
}
});
return list;
}
static List<BootstrapComboFactory<ServerBootstrap, Bootstrap>> sctpChannel() {
List<BootstrapComboFactory<ServerBootstrap, Bootstrap>> list =
new ArrayList<BootstrapComboFactory<ServerBootstrap, Bootstrap>>();
// Make the list of SCTP ServerBootstrap factories.
List<BootstrapFactory<ServerBootstrap>> sbfs = sctpServerChannel();
// Make the list of SCTP Bootstrap factories.
List<BootstrapFactory<Bootstrap>> cbfs = sctpClientChannel();
// Populate the combinations
for (BootstrapFactory<ServerBootstrap> sbf: sbfs) {
for (BootstrapFactory<Bootstrap> cbf: cbfs) {
final BootstrapFactory<ServerBootstrap> sbf0 = sbf;
final BootstrapFactory<Bootstrap> cbf0 = cbf;
list.add(new BootstrapComboFactory<ServerBootstrap, Bootstrap>() {
@Override
public ServerBootstrap newServerInstance() {
return sbf0.newInstance();
}
@Override
public Bootstrap newClientInstance() {
return cbf0.newInstance();
}
});
}
}
return list;
}
private SctpTestPermutation() { }
}

@ -1,20 +0,0 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* Test suite classes for sctp transport
*/
package io.netty.testsuite.transport.sctp;

@ -1,14 +1,11 @@
module org.xbib.io.netty.testsuite {
exports io.netty.testsuite.transport;
exports io.netty.testsuite.transport.sctp;
exports io.netty.testsuite.transport.socket;
exports io.netty.testsuite.util;
requires org.xbib.io.netty.buffer;
requires org.xbib.io.netty.channel;
requires org.xbib.io.netty.util;
requires org.xbib.io.netty.channel.sctp;
requires org.xbib.io.netty.handler.codec;
requires org.xbib.io.netty.handler.codec.sctp;
requires org.xbib.io.netty.handler.codec.spdy;
requires org.xbib.io.netty.handler;
requires org.xbib.io.netty.handler.ssl;

@ -16,13 +16,13 @@ dependencyResolutionManagement {
versionCatalogs {
libs {
version('gradle', '8.5')
version('brotli4j', '1.15.0')
version('brotli4j', '1.16.0')
library('bouncycastle', 'org.bouncycastle', 'bcpkix-jdk18on').version('1.77')
library('conscrypt', 'org.conscrypt', 'conscrypt-openjdk-uber').version('2.5.2')
library('brotli4j', 'com.aayushatharva.brotli4j', 'brotli4j').versionRef('brotli4j')
library('lz4', 'org.lz4', 'lz4-java').version('1.8.0')
library('lzf', 'com.ning', 'compress-lzf').version('1.1.2')
library('zstd', 'com.github.luben', 'zstd-jni').version('1.5.5-11')
library('brotli4j', 'com.aayushatharva.brotli4j', 'brotli4j').versionRef('brotli4j')
library('brotli4j-native-linux-x8664', 'com.aayushatharva.brotli4j', 'native-linux-x86_64').versionRef('brotli4j')
library('brotli4j-native-linux-aarch64', 'com.aayushatharva.brotli4j', 'native-linux-aarch64').versionRef('brotli4j')
library('brotli4j-native-linux-riscv64', 'com.aayushatharva.brotli4j', 'native-linux-riscv64').versionRef('brotli4j')
@ -61,7 +61,6 @@ include 'netty-bzip2'
include 'netty-channel'
include 'netty-channel-epoll'
include 'netty-channel-epoll-native'
include 'netty-channel-sctp'
include 'netty-channel-unix'
include 'netty-channel-unix-native'
include 'netty-handler'
@ -74,7 +73,6 @@ include 'netty-handler-codec-http3'
include 'netty-handler-codec-quic'
include 'netty-handler-codec-quic-native'
include 'netty-handler-codec-rtsp'
include 'netty-handler-codec-sctp'
include 'netty-handler-codec-spdy'
include 'netty-handler-ssl'
include 'netty-handler-ssl-bouncycastle'

@ -8,7 +8,6 @@ dependencies {
testReportAggregation project(':netty-bzip2')
testReportAggregation project(':netty-channel')
testReportAggregation project(':netty-channel-epoll')
testReportAggregation project(':netty-channel-sctp')
testReportAggregation project(':netty-channel-unix')
testReportAggregation project(':netty-handler')
testReportAggregation project(':netty-handler-codec')
@ -19,7 +18,6 @@ dependencies {
testReportAggregation project(':netty-handler-codec-http3')
testReportAggregation project(':netty-handler-codec-quic')
testReportAggregation project(':netty-handler-codec-rtsp')
testReportAggregation project(':netty-handler-codec-sctp')
testReportAggregation project(':netty-handler-codec-spdy')
testReportAggregation project(':netty-handler-ssl')
testReportAggregation project(':netty-handler-ssl-bouncycastle')

Loading…
Cancel
Save