Merge pull request #584 from jestan/master

Netty SCTP transport 4.x
This commit is contained in:
Norman Maurer 2012-09-08 10:50:37 -07:00
commit 36ff79951b
34 changed files with 2173 additions and 1 deletions

View File

@ -39,5 +39,5 @@ Netty is an asynchronous event-driven network application framework for rapid de
- __master__ branch contains code for Netty 4.x
- __3__ branch contains code for Netty 3.x
- __3.2__ branch contains code for Netty 3.x

View File

@ -0,0 +1,101 @@
/*
* 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:
*
* http://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.example.sctp;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.socket.SctpChannel;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSctpChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import java.net.InetSocketAddress;
/**
* Sends one message when a connection is open and echoes back any received
* data to the server over SCTP connection.
*
* Simply put, the echo client initiates the ping-pong
* traffic between the echo client and server by sending the first message to
* the server.
*/
public class SctpEchoClient {
private final String host;
private final int port;
private final int firstMessageSize;
public SctpEchoClient(String host, int port, int firstMessageSize) {
this.host = host;
this.port = port;
this.firstMessageSize = firstMessageSize;
}
public void run() throws Exception {
// Configure the client.
Bootstrap b = new Bootstrap();
try {
b.group(new NioEventLoopGroup())
.channel(new NioSctpChannel())
.option(ChannelOption.SCTP_NODELAY, true)
.remoteAddress(new InetSocketAddress(host, port))
.handler(new ChannelInitializer<SctpChannel>() {
@Override
public void initChannel(SctpChannel ch) throws Exception {
ch.pipeline().addLast(
new LoggingHandler(LogLevel.INFO),
new SctpEchoClientHandler(firstMessageSize));
}
});
// Start the client.
ChannelFuture f = b.connect().sync();
// Wait until the connection is closed.
f.channel().closeFuture().sync();
} finally {
// Shut down the event loop to terminate all threads.
b.shutdown();
}
}
public static void main(String[] args) throws Exception {
// Print usage if no argument is specified.
if (args.length < 2 || args.length > 3) {
System.err.println(
"Usage: " + SctpEchoClient.class.getSimpleName() +
" <host> <port> [<first message size>]");
return;
}
// Parse options.
final String host = "localhost";
final int port = Integer.parseInt(args[1]);
final int firstMessageSize;
if (args.length == 3) {
firstMessageSize = Integer.parseInt(args[2]);
} else {
firstMessageSize = 256;
}
new SctpEchoClient(host, port, firstMessageSize).run();
}
}

View File

@ -0,0 +1,76 @@
/*
* 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:
*
* http://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.example.sctp;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.MessageBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
import io.netty.channel.socket.SctpData;
import io.netty.channel.socket.SctpMessage;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Handler implementation for the SCTP echo client. It initiates the ping-pong
* traffic between the echo client and server by sending the first message to
* the server.
*/
public class SctpEchoClientHandler extends ChannelInboundMessageHandlerAdapter<SctpMessage> {
private static final Logger logger = Logger.getLogger(
SctpEchoClientHandler.class.getName());
private final ByteBuf firstMessage;
/**
* Creates a client-side handler.
*/
public SctpEchoClientHandler(int firstMessageSize) {
if (firstMessageSize <= 0) {
throw new IllegalArgumentException("firstMessageSize: " + firstMessageSize);
}
firstMessage = Unpooled.buffer(firstMessageSize);
for (int i = 0; i < firstMessage.capacity(); i++) {
firstMessage.writeByte((byte) i);
}
}
@Override
public void channelActive(ChannelHandlerContext ctx) {
ctx.write(new SctpData(0, 0, firstMessage));
}
@Override
public void messageReceived(ChannelHandlerContext ctx, SctpMessage msg) throws Exception {
if (msg instanceof SctpData) {
MessageBuf<Object> out = ctx.nextOutboundMessageBuffer();
out.add(msg);
ctx.flush();
} else {
logger.log(Level.INFO, "Received SCTP Notification", msg);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
// Close the connection when an exception is raised.
logger.log(Level.WARNING, "Unexpected exception from downstream.", cause);
ctx.close();
}
}

View File

@ -0,0 +1,82 @@
/*
* 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:
*
* http://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.example.sctp;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.socket.SctpChannel;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSctpServerChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import java.net.InetSocketAddress;
/**
* Echoes back any received data from a SCTP client.
*/
public class SctpEchoServer {
private final int port;
public SctpEchoServer(int port) {
this.port = port;
}
public void run() throws Exception {
// Configure the server.
ServerBootstrap b = new ServerBootstrap();
try {
b.group(new NioEventLoopGroup(), new NioEventLoopGroup())
.channel(new NioSctpServerChannel())
.option(ChannelOption.SO_BACKLOG, 100)
.localAddress(new InetSocketAddress(port))
.childOption(ChannelOption.SCTP_NODELAY, true)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SctpChannel>() {
@Override
public void initChannel(SctpChannel ch) throws Exception {
ch.pipeline().addLast(
new LoggingHandler(LogLevel.INFO),
new SctpEchoServerHandler());
}
});
// Start the server.
ChannelFuture f = b.bind().sync();
// Wait until the server socket is closed.
f.channel().closeFuture().sync();
} finally {
// Shut down all event loops to terminate all threads.
b.shutdown();
}
}
public static void main(String[] args) throws Exception {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 2556;
}
new SctpEchoServer(port).run();
}
}

View File

@ -0,0 +1,54 @@
/*
* 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:
*
* http://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.example.sctp;
import io.netty.buffer.MessageBuf;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
import io.netty.channel.socket.SctpData;
import io.netty.channel.socket.SctpMessage;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Handler implementation for the SCTP echo server.
*/
@Sharable
public class SctpEchoServerHandler extends ChannelInboundMessageHandlerAdapter<SctpMessage> {
private static final Logger logger = Logger.getLogger(
SctpEchoServerHandler.class.getName());
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
// Close the connection when an exception is raised.
logger.log(Level.WARNING, "Unexpected exception from downstream.", cause);
ctx.close();
}
@Override
public void messageReceived(ChannelHandlerContext ctx, SctpMessage msg) throws Exception {
if (msg instanceof SctpData) {
MessageBuf<Object> out = ctx.nextOutboundMessageBuffer();
out.add(msg);
ctx.flush();
} else {
logger.log(Level.INFO, "Received SCTP Notification", msg);
}
}
}

View File

@ -35,5 +35,19 @@
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<excludes>
<!-- Exclude the com.sun.nio stuff as this is included in the jdk if its supported by the running os -->
<exclude>**/com/**</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,42 @@
/*
* 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:
*
* http://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 com.sun.nio.sctp;
public class AbstractNotificationHandler<T> implements NotificationHandler<T> {
static {
UnsupportedOperatingSystemException.raise();
}
public HandlerResult handleNotification(AssociationChangeNotification notification, Object o) {
return null;
}
public HandlerResult handleNotification(Notification notification, Object o) {
return null;
}
public HandlerResult handleNotification(PeerAddressChangeNotification notification, Object o) {
return null;
}
public HandlerResult handleNotification(SendFailedNotification notification, Object o) {
return null;
}
public HandlerResult handleNotification(ShutdownNotification notification, Object o) {
return null;
}
}

View File

@ -0,0 +1,22 @@
/*
* 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:
*
* http://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 com.sun.nio.sctp;
public class Association {
static {
UnsupportedOperatingSystemException.raise();
}
}

View File

@ -0,0 +1,22 @@
/*
* 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:
*
* http://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 com.sun.nio.sctp;
public abstract class AssociationChangeNotification implements Notification {
static {
UnsupportedOperatingSystemException.raise();
}
}

View File

@ -0,0 +1,25 @@
/*
* 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:
*
* http://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 com.sun.nio.sctp;
/**
* TODO Document me.
*
* @author <a href="http://gleamynode.net/">Trustin Lee</a>
*/
public enum HandlerResult {
CONTINUE, RETURN;
}

View File

@ -0,0 +1,38 @@
/*
* 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:
*
* http://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 com.sun.nio.sctp;
import java.net.SocketAddress;
public abstract class MessageInfo {
static {
UnsupportedOperatingSystemException.raise();
}
public static MessageInfo createOutgoing(Association association, SocketAddress address, int streamNumber) {
return null;
}
public abstract SocketAddress address();
public abstract int streamNumber();
public abstract MessageInfo streamNumber(int streamNumber);
public abstract int payloadProtocolID();
public abstract MessageInfo payloadProtocolID(int ppid);
public abstract boolean isComplete();
public abstract boolean isUnordered();
public abstract MessageInfo unordered(boolean b);
}

View File

@ -0,0 +1,20 @@
/*
* 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:
*
* http://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 com.sun.nio.sctp;
public interface Notification {
Association association();
}

View File

@ -0,0 +1,19 @@
/*
* 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:
*
* http://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 com.sun.nio.sctp;
public interface NotificationHandler<T> {
}

View File

@ -0,0 +1,22 @@
/*
* 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:
*
* http://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 com.sun.nio.sctp;
public abstract class PeerAddressChangeNotification implements Notification {
static {
UnsupportedOperatingSystemException.raise();
}
}

View File

@ -0,0 +1,57 @@
/*
* 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:
*
* http://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 com.sun.nio.sctp;
import java.io.IOException;
import java.net.InetAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.spi.AbstractSelectableChannel;
import java.nio.channels.spi.SelectorProvider;
import java.util.Set;
public abstract class SctpChannel extends AbstractSelectableChannel {
static {
UnsupportedOperatingSystemException.raise();
}
public static SctpChannel open() throws IOException {
return null;
}
protected SctpChannel(SelectorProvider provider) {
super(provider);
}
public abstract <T> T getOption(SctpSocketOption<T> name) throws IOException;
public abstract <T> SctpChannel setOption(SctpSocketOption<T> name, T value) throws IOException;
public abstract Set<SocketAddress> getAllLocalAddresses() throws IOException;
public abstract Set<SocketAddress> getRemoteAddresses() throws IOException;
public abstract Association association() throws IOException;
public abstract SctpChannel bind(SocketAddress local) throws IOException;
public abstract boolean connect(SocketAddress remote) throws IOException;
public abstract boolean finishConnect() throws IOException;
public abstract SctpChannel bindAddress(InetAddress inetAddress) throws IOException;
public abstract SctpChannel unbindAddress(InetAddress inetAddress) throws IOException;
public abstract <T> MessageInfo receive(ByteBuffer dst, T attachment, NotificationHandler<T> handler) throws IOException;
public abstract int send(ByteBuffer src, MessageInfo messageInfo) throws IOException;
public abstract Set<SctpSocketOption<?>> supportedOptions();
}

View File

@ -0,0 +1,50 @@
/*
* 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:
*
* http://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 com.sun.nio.sctp;
import java.io.IOException;
import java.net.InetAddress;
import java.net.SocketAddress;
import java.nio.channels.spi.AbstractSelectableChannel;
import java.nio.channels.spi.SelectorProvider;
import java.util.Set;
public abstract class SctpServerChannel extends AbstractSelectableChannel {
static {
UnsupportedOperatingSystemException.raise();
}
public static SctpServerChannel open() throws IOException {
return null;
}
protected SctpServerChannel(SelectorProvider provider) {
super(provider);
}
public abstract <T> T getOption(SctpSocketOption<T> name) throws IOException;
public abstract <T> SctpChannel setOption(SctpSocketOption<T> name, T value) throws IOException;
public abstract Set<SocketAddress> getAllLocalAddresses() throws IOException;
public abstract SctpServerChannel bind(SocketAddress local) throws IOException;
public abstract SctpServerChannel bind(SocketAddress local, int backlog) throws IOException;
public abstract SctpServerChannel bindAddress(InetAddress inetAddress) throws IOException;
public abstract SctpServerChannel unbindAddress(InetAddress inetAddress) throws IOException;
public abstract SctpChannel accept() throws IOException;
}

View File

@ -0,0 +1,21 @@
/*
* 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:
*
* http://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 com.sun.nio.sctp;
public interface SctpSocketOption<T> {
String name();
Class<T> type();
}

View File

@ -0,0 +1,51 @@
/*
* 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:
*
* http://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 com.sun.nio.sctp;
import java.net.SocketAddress;
public class SctpStandardSocketOptions {
static {
UnsupportedOperatingSystemException.raise();
}
public static final SctpSocketOption<Boolean> SCTP_DISABLE_FRAGMENTS = null;
public static final SctpSocketOption<Boolean> SCTP_EXPLICIT_COMPLETE = null;
public static final SctpSocketOption<Integer> SCTP_FRAGMENT_INTERLEAVE = null;
public static final SctpSocketOption<InitMaxStreams> SCTP_INIT_MAXSTREAMS = null;
public static final SctpSocketOption<Boolean> SCTP_NODELAY = null;
public static final SctpSocketOption<SocketAddress> SCTP_PRIMARY_ADDR = null;
public static final SctpSocketOption<SocketAddress> SCTP_SET_PEER_PRIMARY_ADDR = null;
public static final SctpSocketOption<Integer> SO_LINGER = null;
public static final SctpSocketOption<Integer> SO_RCVBUF = null;
public static final SctpSocketOption<Integer> SO_SNDBUF = null;
public static class InitMaxStreams {
public static InitMaxStreams create(int i, int i1) {
return null;
}
public int maxInStreams() {
return 0;
}
public int maxOutStreams() {
return 0;
}
}
}

View File

@ -0,0 +1,22 @@
/*
* 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:
*
* http://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 com.sun.nio.sctp;
public abstract class SendFailedNotification implements Notification {
static {
UnsupportedOperatingSystemException.raise();
}
}

View File

@ -0,0 +1,22 @@
/*
* 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:
*
* http://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 com.sun.nio.sctp;
public abstract class ShutdownNotification implements Notification {
static {
UnsupportedOperatingSystemException.raise();
}
}

View File

@ -0,0 +1,41 @@
/*
* 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:
*
* http://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 com.sun.nio.sctp;
public class UnsupportedOperatingSystemException extends RuntimeException {
private static final long serialVersionUID = -221782446524784377L;
public static void raise() {
throw new UnsupportedOperatingSystemException();
}
public UnsupportedOperatingSystemException() {
super();
}
public UnsupportedOperatingSystemException(String message) {
super(message);
}
public UnsupportedOperatingSystemException(String message, Throwable cause) {
super(message, cause);
}
public UnsupportedOperatingSystemException(Throwable cause) {
super(cause);
}
}

View File

@ -0,0 +1,22 @@
/*
* 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:
*
* http://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.
*/
/**
* This package is only included to let SCTP also compile on non-unix operation systems.
*
* <strong>This will not get included in the generated jar!</strong>
*/
package com.sun.nio.sctp;

View File

@ -0,0 +1,156 @@
/*
* 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:
*
* http://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.socket;
import com.sun.nio.sctp.SctpChannel;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelOption;
import io.netty.channel.DefaultChannelConfig;
import java.io.IOException;
import java.util.Map;
import com.sun.nio.sctp.SctpStandardSocketOptions;
import static io.netty.channel.ChannelOption.*;
/**
* The default {@link SctpChannelConfig} implementation for SCTP.
*/
public class DefaultSctpChannelConfig extends DefaultChannelConfig implements SctpChannelConfig {
private SctpChannel channel;
public DefaultSctpChannelConfig(SctpChannel channel) {
if (channel == null) {
throw new NullPointerException("channel");
}
this.channel = channel;
}
@Override
public Map<ChannelOption<?>, Object> getOptions() {
return getOptions(
super.getOptions(),
SO_RCVBUF, SO_SNDBUF, SCTP_NODELAY, SCTP_INIT_MAXSTREAMS);
}
@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());
}
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 channel.getOption(SctpStandardSocketOptions.SCTP_NODELAY);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public void setSctpNoDelay(boolean sctpNoDelay) {
try {
channel.setOption(SctpStandardSocketOptions.SCTP_NODELAY, sctpNoDelay);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public int getSendBufferSize() {
try {
return channel.getOption(SctpStandardSocketOptions.SO_SNDBUF);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public void setSendBufferSize(int sendBufferSize) {
try {
channel.setOption(SctpStandardSocketOptions.SO_SNDBUF, sendBufferSize);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public int getReceiveBufferSize() {
try {
return channel.getOption(SctpStandardSocketOptions.SO_RCVBUF);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public void setReceiveBufferSize(int receiveBufferSize) {
try {
channel.setOption(SctpStandardSocketOptions.SO_RCVBUF, receiveBufferSize);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public SctpStandardSocketOptions.InitMaxStreams getInitMaxStreams() {
try {
return channel.getOption(SctpStandardSocketOptions.SCTP_INIT_MAXSTREAMS);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public void setInitMaxStreams(SctpStandardSocketOptions.InitMaxStreams initMaxStreams) {
try {
channel.setOption(SctpStandardSocketOptions.SCTP_INIT_MAXSTREAMS, initMaxStreams);
} catch (IOException e) {
throw new ChannelException(e);
}
}
}

View File

@ -0,0 +1,153 @@
/*
* 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:
*
* http://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.socket;
import com.sun.nio.sctp.SctpServerChannel;
import com.sun.nio.sctp.SctpStandardSocketOptions;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelOption;
import io.netty.channel.DefaultChannelConfig;
import io.netty.util.NetworkConstants;
import java.io.IOException;
import java.util.Map;
import static com.sun.nio.sctp.SctpStandardSocketOptions.SCTP_INIT_MAXSTREAMS;
import static com.sun.nio.sctp.SctpStandardSocketOptions.SO_RCVBUF;
import static com.sun.nio.sctp.SctpStandardSocketOptions.SO_SNDBUF;
import static io.netty.channel.ChannelOption.SCTP_NODELAY;
/**
* The default {@link SctpServerChannelConfig} implementation for SCTP.
*/
public class DefaultSctpServerChannelConfig extends DefaultChannelConfig implements SctpServerChannelConfig {
private final SctpServerChannel serverChannel;
private volatile int backlog = NetworkConstants.SOMAXCONN;
/**
* Creates a new instance.
*/
public DefaultSctpServerChannelConfig(com.sun.nio.sctp.SctpServerChannel serverChannel) {
if (serverChannel == null) {
throw new NullPointerException("serverChannel");
}
this.serverChannel = serverChannel;
}
@Override
public Map<ChannelOption<?>, Object> getOptions() {
return getOptions(
super.getOptions(),
ChannelOption.SO_RCVBUF, ChannelOption.SO_SNDBUF, ChannelOption.SCTP_INIT_MAXSTREAMS);
}
@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());
}
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 == ChannelOption.SCTP_INIT_MAXSTREAMS) {
setInitMaxStreams((SctpStandardSocketOptions.InitMaxStreams) value);
} else {
return super.setOption(option, value);
}
return true;
}
@Override
public int getSendBufferSize() {
try {
return serverChannel.getOption(SO_SNDBUF);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public void setSendBufferSize(int sendBufferSize) {
try {
serverChannel.setOption(SO_SNDBUF, sendBufferSize);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public int getReceiveBufferSize() {
try {
return serverChannel.getOption(SO_RCVBUF);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public void setReceiveBufferSize(int receiveBufferSize) {
try {
serverChannel.setOption(SO_RCVBUF, receiveBufferSize);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public SctpStandardSocketOptions.InitMaxStreams getInitMaxStreams() {
try {
return serverChannel.getOption(SCTP_INIT_MAXSTREAMS);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public void setInitMaxStreams(SctpStandardSocketOptions.InitMaxStreams initMaxStreams) {
try {
serverChannel.setOption(SCTP_INIT_MAXSTREAMS, initMaxStreams);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public int getBacklog() {
return backlog;
}
@Override
public void setBacklog(int backlog) {
if (backlog < 0) {
throw new IllegalArgumentException("backlog: " + backlog);
}
this.backlog = backlog;
}
}

View File

@ -0,0 +1,81 @@
/*
* 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:
*
* http://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.socket;
import com.sun.nio.sctp.Association;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Set;
/**
* A SCTP/IP {@link io.netty.channel.Channel}
*/
public interface SctpChannel extends Channel {
/**
* 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
SocketAddress 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<SocketAddress> 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
SocketAddress 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<SocketAddress> allRemoteAddresses();
}

View File

@ -0,0 +1,94 @@
/*
* 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:
*
* http://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.socket;
import io.netty.channel.ChannelConfig;
import static com.sun.nio.sctp.SctpStandardSocketOptions.InitMaxStreams;
/**
* A {@link io.netty.channel.ChannelConfig} for a {@link SctpChannel}.
* <p/>
* <h3>Available options</h3>
* <p/>
* In addition to the options provided by {@link io.netty.channel.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>{@code "sctpNoDelay"}</td><td>{@link #setSctpNoDelay(boolean)}}</td>
* </tr><tr>
* <td>{@code "receiveBufferSize"}</td><td>{@link #setReceiveBufferSize(int)}</td>
* </tr><tr>
* <td>{@code "sendBufferSize"}</td><td>{@link #setSendBufferSize(int)}</td>
* </tr><tr>
* <td>{@code "sctpInitMaxStreams"}</td>
* <td>{@link #setInitMaxStreams(com.sun.nio.sctp.SctpStandardSocketOptions.InitMaxStreams)}</td>
* </tr>
* </table>
*/
public interface SctpChannelConfig extends ChannelConfig {
/**
* Gets the <a href="http://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SCTP_NODELAY}</a> option.
*/
boolean isSctpNoDelay();
/**
* Sets the <a href="http://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SCTP_NODELAY}</a> option.
*/
void setSctpNoDelay(boolean sctpNoDelay);
/**
* Gets the <a href="http://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SO_SNDBUF}</a> option.
*/
int getSendBufferSize();
/**
* Sets the <a href="http://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SO_SNDBUF}</a> option.
*/
void setSendBufferSize(int sendBufferSize);
/**
* Gets the <a href="http://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SO_RCVBUF}</a> option.
*/
int getReceiveBufferSize();
/**
* Gets the <a href="http://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SO_RCVBUF}</a> option.
*/
void setReceiveBufferSize(int receiveBufferSize);
/**
* Gets the <a href="http://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SCTP_INIT_MAXSTREAMS}</a> option.
*/
InitMaxStreams getInitMaxStreams();
/**
* Gets the <a href="http://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SCTP_INIT_MAXSTREAMS}</a> option.
*/
void setInitMaxStreams(InitMaxStreams initMaxStreams);
}

View File

@ -0,0 +1,120 @@
/*
* 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:
*
* http://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.socket;
import com.sun.nio.sctp.MessageInfo;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
/**
* Representation of SCTP Data Chunk
*/
public final class SctpData implements SctpMessage {
private final int streamIdentifier;
private final int protocolIdentifier;
private final ByteBuf payloadBuffer;
private 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 SctpData(int protocolIdentifier, int streamIdentifier, ByteBuf payloadBuffer) {
this.protocolIdentifier = protocolIdentifier;
this.streamIdentifier = streamIdentifier;
this.payloadBuffer = payloadBuffer;
}
public SctpData(MessageInfo msgInfo, ByteBuf payloadBuffer) {
this.msgInfo = msgInfo;
this.streamIdentifier = msgInfo.streamNumber();
this.protocolIdentifier = msgInfo.payloadProtocolID();
this.payloadBuffer = payloadBuffer;
}
public int getStreamIdentifier() {
return streamIdentifier;
}
public int getProtocolIdentifier() {
return protocolIdentifier;
}
public ByteBuf getPayloadBuffer() {
if (payloadBuffer.readable()) {
return payloadBuffer.slice();
} else {
return Unpooled.EMPTY_BUFFER;
}
}
public MessageInfo getMessageInfo() {
return msgInfo;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
SctpData sctpFrame = (SctpData) o;
if (protocolIdentifier != sctpFrame.protocolIdentifier) {
return false;
}
if (streamIdentifier != sctpFrame.streamIdentifier) {
return false;
}
if (!payloadBuffer.equals(sctpFrame.payloadBuffer)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result = streamIdentifier;
result = 31 * result + protocolIdentifier;
result = 31 * result + payloadBuffer.hashCode();
return result;
}
@Override
public String toString() {
return new StringBuilder().
append("SctpFrame{").
append("streamIdentifier=").
append(streamIdentifier).
append(", protocolIdentifier=").
append(protocolIdentifier).
append(", payloadBuffer=").
append(ByteBufUtil.hexDump(getPayloadBuffer())).
append('}').toString();
}
}

View File

@ -0,0 +1,22 @@
/*
* 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:
*
* http://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.socket;
/**
* A marker interface for a SCTP/IP message
*/
public interface SctpMessage {
}

View File

@ -0,0 +1,74 @@
/*
* 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:
*
* http://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.socket;
import com.sun.nio.sctp.Notification;
public final class SctpNotification implements SctpMessage {
private Notification notification;
private Object attachment;
public SctpNotification(Notification notification, Object attachment) {
this.notification = notification;
this.attachment = attachment;
}
public Notification notification() {
return notification;
}
public Object attachment() {
return attachment;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
SctpNotification that = (SctpNotification) o;
if (!attachment.equals(that.attachment)) {
return false;
}
if (!notification.equals(that.notification)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result = notification.hashCode();
result = 31 * result + attachment.hashCode();
return result;
}
@Override
public String toString() {
return "SctpNotification{" +
"notification=" + notification +
", attachment=" + attachment +
'}';
}
}

View File

@ -0,0 +1,65 @@
/*
* 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:
*
* http://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.socket;
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;
public class SctpNotificationHandler extends AbstractNotificationHandler<Object> {
private final SctpChannel sctpChannel;
private final ChannelPipeline pipeline;
public SctpNotificationHandler(SctpChannel sctpChannel) {
this.sctpChannel = sctpChannel;
pipeline = sctpChannel.pipeline();
}
@Override
public HandlerResult handleNotification(AssociationChangeNotification notification, Object o) {
updateInboundBuffer(notification, o);
return HandlerResult.CONTINUE;
}
@Override
public HandlerResult handleNotification(PeerAddressChangeNotification notification, Object o) {
updateInboundBuffer(notification, o);
return HandlerResult.CONTINUE;
}
@Override
public HandlerResult handleNotification(SendFailedNotification notification, Object o) {
updateInboundBuffer(notification, o);
return HandlerResult.CONTINUE;
}
@Override
public HandlerResult handleNotification(ShutdownNotification notification, Object o) {
sctpChannel.close();
return HandlerResult.RETURN;
}
private void updateInboundBuffer(Notification notification, Object o) {
pipeline.inboundMessageBuffer().add(new SctpNotification(notification, o));
}
}

View File

@ -0,0 +1,55 @@
/*
* 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:
*
* http://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.socket;
import io.netty.channel.ServerChannel;
import java.net.SocketAddress;
import java.util.Set;
/**
* A SCTP/IP {@link io.netty.channel.ServerChannel} which accepts incoming SCTP/IP connections.
*
* The {@link SctpServerChannel} provides the additional operations, available in the
* underlying JDK SCTP Server Channel like multi-homing etc.
*/
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
SocketAddress 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<SocketAddress> allLocalAddresses();
}

View File

@ -0,0 +1,95 @@
/*
* 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:
*
* http://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.socket;
import io.netty.channel.ChannelConfig;
import static com.sun.nio.sctp.SctpStandardSocketOptions.InitMaxStreams;
/**
* A {@link io.netty.channel.ChannelConfig} for a {@link SctpServerChannelConfig}.
* <p/>
* <h3>Available options</h3>
* <p/>
* In addition to the options provided by {@link io.netty.channel.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>{@code "backlog"}</td><td>{@link #setBacklog(int)}</td>
* </tr><tr>
* * <td>{@code "receiveBufferSize"}</td><td>{@link #setReceiveBufferSize(int)}</td>
* </tr><tr>
* <td>{@code "sendBufferSize"}</td><td>{@link #setSendBufferSize(int)}</td>
* </tr><tr>
* <td>{@code "sctpInitMaxStreams"}</td>
* <td>{@link #setInitMaxStreams(com.sun.nio.sctp.SctpStandardSocketOptions.InitMaxStreams)} (int)}}</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.
*/
void setBacklog(int backlog);
/**
* Gets the <a href="http://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SO_SNDBUF}</a> option.
*/
int getSendBufferSize();
/**
* Sets the <a href="http://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SO_SNDBUF}</a> option.
*/
void setSendBufferSize(int sendBufferSize);
/**
* Gets the <a href="http://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SO_RCVBUF}</a> option.
*/
int getReceiveBufferSize();
/**
* Gets the <a href="http://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SO_RCVBUF}</a> option.
*/
void setReceiveBufferSize(int receiveBufferSize);
/**
* Gets the <a href="http://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SCTP_INIT_MAXSTREAMS}</a> option.
*/
InitMaxStreams getInitMaxStreams();
/**
* Gets the <a href="http://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SCTP_INIT_MAXSTREAMS}</a> option.
*/
void setInitMaxStreams(InitMaxStreams initMaxStreams);
}

View File

@ -0,0 +1,280 @@
/*
* 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:
*
* http://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.socket.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.ChannelBufType;
import io.netty.buffer.MessageBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelMetadata;
import io.netty.channel.socket.DefaultSctpChannelConfig;
import io.netty.channel.socket.SctpChannelConfig;
import io.netty.channel.socket.SctpData;
import io.netty.channel.socket.SctpNotificationHandler;
import io.netty.logging.InternalLogger;
import io.netty.logging.InternalLoggerFactory;
import java.io.IOException;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class NioSctpChannel extends AbstractNioMessageChannel implements io.netty.channel.socket.SctpChannel {
private static final ChannelMetadata METADATA = new ChannelMetadata(ChannelBufType.MESSAGE, 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);
}
}
public NioSctpChannel() {
this(newSctpChannel());
}
public NioSctpChannel(SctpChannel sctpChannel) {
this(null, null, sctpChannel);
}
public NioSctpChannel(Channel parent, Integer id, SctpChannel sctpChannel) {
super(parent, id, sctpChannel, SelectionKey.OP_READ);
try {
sctpChannel.configureBlocking(false);
} 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);
}
config = new DefaultSctpChannelConfig(sctpChannel);
notificationHandler = new SctpNotificationHandler(this);
}
@Override
public ChannelMetadata metadata() {
return METADATA;
}
@Override
public Association association() {
try {
return javaChannel().association();
} catch (IOException e) {
return null;
}
}
@Override
public Set<SocketAddress> allLocalAddresses() {
try {
final Set<SocketAddress> allLocalAddresses = javaChannel().getAllLocalAddresses();
final Set<SocketAddress> addresses = new HashSet<SocketAddress>(allLocalAddresses.size());
for (SocketAddress socketAddress : allLocalAddresses) {
addresses.add(socketAddress);
}
return addresses;
} catch (Throwable t) {
return Collections.emptySet();
}
}
@Override
public SctpChannelConfig config() {
return config;
}
@Override
public Set<SocketAddress> allRemoteAddresses() {
try {
final Set<SocketAddress> allLocalAddresses = javaChannel().getRemoteAddresses();
final Set<SocketAddress> addresses = new HashSet<SocketAddress>(allLocalAddresses.size());
for (SocketAddress socketAddress : allLocalAddresses) {
addresses.add(socketAddress);
}
return addresses;
} catch (Throwable t) {
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 {
for (SocketAddress address : javaChannel().getAllLocalAddresses()) {
return address;
}
} catch (IOException e) {
// ignore
}
return null;
}
@Override
protected SocketAddress remoteAddress0() {
try {
for (SocketAddress address : javaChannel().getRemoteAddresses()) {
return address;
}
} 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_READ);
} else {
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();
}
selectionKey().interestOps(SelectionKey.OP_READ);
}
@Override
protected void doDisconnect() throws Exception {
doClose();
}
@Override
protected void doClose() throws Exception {
javaChannel().close();
}
@Override
protected int doReadMessages(MessageBuf<Object> buf) throws Exception {
SctpChannel ch = javaChannel();
ByteBuffer data = ByteBuffer.allocate(config().getReceiveBufferSize());
MessageInfo messageInfo = ch.receive(data, null, notificationHandler);
if (messageInfo == null) {
return 0;
}
data.flip();
buf.add(new SctpData(messageInfo, Unpooled.wrappedBuffer(data)));
return 1;
}
@Override
protected int doWriteMessages(MessageBuf<Object> buf, boolean lastSpin) throws Exception {
SctpData packet = (SctpData) buf.peek();
ByteBuf data = packet.getPayloadBuffer();
int dataLen = data.readableBytes();
ByteBuffer nioData;
if (data.hasNioBuffer()) {
nioData = data.nioBuffer();
} else {
nioData = ByteBuffer.allocate(dataLen);
data.getBytes(data.readerIndex(), nioData);
nioData.flip();
}
final MessageInfo messageInfo = MessageInfo.createOutgoing(association(), null, packet.getStreamIdentifier());
messageInfo.payloadProtocolID(packet.getProtocolIdentifier());
messageInfo.streamNumber(packet.getStreamIdentifier());
final int writtenBytes = javaChannel().send(nioData, messageInfo);
final SelectionKey key = selectionKey();
final int interestOps = key.interestOps();
if (writtenBytes <= 0 && dataLen > 0) {
// Did not write a packet.
// 1) If 'lastSpin' is false, the caller will call this method again real soon.
// - Do not update OP_WRITE.
// 2) If 'lastSpin' is true, the caller will not retry.
// - Set OP_WRITE so that the event loop calls flushForcibly() later.
if (lastSpin) {
if ((interestOps & SelectionKey.OP_WRITE) == 0) {
key.interestOps(interestOps | SelectionKey.OP_WRITE);
}
}
return 0;
}
// Wrote a packet.
buf.remove();
if (buf.isEmpty()) {
// Wrote the outbound buffer completely - clear OP_WRITE.
if ((interestOps & SelectionKey.OP_WRITE) != 0) {
key.interestOps(interestOps & ~SelectionKey.OP_WRITE);
}
}
return 1;
}
}

View File

@ -0,0 +1,154 @@
/*
* 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:
*
* http://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.socket.nio;
import com.sun.nio.sctp.SctpChannel;
import com.sun.nio.sctp.SctpServerChannel;
import io.netty.buffer.ChannelBufType;
import io.netty.buffer.MessageBuf;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelMetadata;
import io.netty.channel.socket.DefaultSctpServerChannelConfig;
import io.netty.channel.socket.SctpServerChannelConfig;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.channels.SelectionKey;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class NioSctpServerChannel extends AbstractNioMessageChannel
implements io.netty.channel.socket.SctpServerChannel {
private static final ChannelMetadata METADATA = new ChannelMetadata(ChannelBufType.MESSAGE, false);
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;
public NioSctpServerChannel() {
super(null, null, newSocket(), SelectionKey.OP_ACCEPT);
config = new DefaultSctpServerChannelConfig(this.javaChannel());
}
@Override
public ChannelMetadata metadata() {
return METADATA;
}
@Override
public Set<SocketAddress> allLocalAddresses() {
try {
final Set<SocketAddress> allLocalAddresses = javaChannel().getAllLocalAddresses();
final Set<SocketAddress> addresses = new HashSet<SocketAddress>(allLocalAddresses.size());
for (SocketAddress socketAddress : allLocalAddresses) {
addresses.add(socketAddress);
}
return addresses;
} catch (Throwable t) {
return Collections.emptySet();
}
}
@Override
public SctpServerChannelConfig config() {
return config;
}
@Override
public boolean isActive() {
return isOpen() && !allLocalAddresses().isEmpty();
}
@Override
public InetSocketAddress remoteAddress() {
return null;
}
@Override
protected SctpServerChannel javaChannel() {
return (SctpServerChannel) super.javaChannel();
}
@Override
protected SocketAddress localAddress0() {
try {
for (SocketAddress address : javaChannel().getAllLocalAddresses()) {
return address;
}
} catch (IOException e) {
// ignore
}
return null;
}
@Override
protected void doBind(SocketAddress localAddress) throws Exception {
javaChannel().bind(localAddress, config.getBacklog());
SelectionKey selectionKey = selectionKey();
selectionKey.interestOps(selectionKey.interestOps() | SelectionKey.OP_ACCEPT);
}
@Override
protected void doClose() throws Exception {
javaChannel().close();
}
@Override
protected int doReadMessages(MessageBuf<Object> buf) throws Exception {
SctpChannel ch = javaChannel().accept();
if (ch == null) {
return 0;
}
buf.add(new NioSctpChannel(this, null, ch));
return 1;
}
// 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 int doWriteMessages(MessageBuf<Object> buf, boolean lastSpin) throws Exception {
throw new UnsupportedOperationException();
}
}