move sctp to netty-contrib
This commit is contained in:
parent
938371e9eb
commit
1b906bf706
42 changed files with 11 additions and 3680 deletions
|
@ -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 (>= 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 (< 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 <= 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 <= 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 <= 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 <= 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 && 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 'b;'}, {@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 & 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 & 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…
Reference in a new issue