Code clean up
This commit is contained in:
parent
b6aa509f32
commit
d24c48cbfb
@ -49,7 +49,15 @@ public abstract class AbstractChannelSink implements ChannelSink {
|
|||||||
fireExceptionCaught(event.getChannel(), actualCause);
|
fireExceptionCaught(event.getChannel(), actualCause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code true} if and only if the specified {@code actualCause}, which was raised while
|
||||||
|
* handling the specified {@code event}, must trigger an {@code exceptionCaught()} event in
|
||||||
|
* an I/O thread.
|
||||||
|
*
|
||||||
|
* @param event the event which raised exception
|
||||||
|
* @param actualCause the raised exception
|
||||||
|
*/
|
||||||
protected boolean isFireExceptionCaughtLater(ChannelEvent event, Throwable actualCause) {
|
protected boolean isFireExceptionCaughtLater(ChannelEvent event, Throwable actualCause) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ public class ChannelLocal<T> implements Iterable<Entry<Channel, T>> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private final boolean removeOnClose;
|
private final boolean removeOnClose;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link Channel} local variable by calling {@link #ChannelLocal(boolean)} with <code>false</code> as parameter
|
* Creates a {@link Channel} local variable by calling {@link #ChannelLocal(boolean)} with <code>false</code> as parameter
|
||||||
*/
|
*/
|
||||||
@ -65,6 +65,8 @@ public class ChannelLocal<T> implements Iterable<Entry<Channel, T>> {
|
|||||||
/**
|
/**
|
||||||
* Returns the initial value of the variable. By default, it returns
|
* Returns the initial value of the variable. By default, it returns
|
||||||
* {@code null}. Override it to change the initial value.
|
* {@code null}. Override it to change the initial value.
|
||||||
|
*
|
||||||
|
* @param channel the channel where this local variable is accessed with
|
||||||
*/
|
*/
|
||||||
protected T initialValue(Channel channel) {
|
protected T initialValue(Channel channel) {
|
||||||
return null;
|
return null;
|
||||||
@ -125,7 +127,7 @@ public class ChannelLocal<T> implements Iterable<Entry<Channel, T>> {
|
|||||||
throw new NullPointerException("channel");
|
throw new NullPointerException("channel");
|
||||||
}
|
}
|
||||||
T mapping = map.putIfAbsent(channel, value);
|
T mapping = map.putIfAbsent(channel, value);
|
||||||
|
|
||||||
if (removeOnClose && mapping == null) {
|
if (removeOnClose && mapping == null) {
|
||||||
channel.getCloseFuture().addListener(remover);
|
channel.getCloseFuture().addListener(remover);
|
||||||
}
|
}
|
||||||
|
@ -338,7 +338,7 @@ public class DefaultChannelFuture implements ChannelFuture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkDeadLock() {
|
private static void checkDeadLock() {
|
||||||
if (isUseDeadLockChecker() && DeadLockProofWorker.PARENT.get() != null) {
|
if (isUseDeadLockChecker() && DeadLockProofWorker.PARENT.get() != null) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"await*() in I/O thread causes a dead lock or " +
|
"await*() in I/O thread causes a dead lock or " +
|
||||||
|
@ -316,7 +316,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
return ctx.getHandler();
|
return ctx.getHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void callBeforeAdd(ChannelHandlerContext ctx) {
|
private static void callBeforeAdd(ChannelHandlerContext ctx) {
|
||||||
if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
|
if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -366,7 +366,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void callBeforeRemove(ChannelHandlerContext ctx) {
|
private static void callBeforeRemove(ChannelHandlerContext ctx) {
|
||||||
if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
|
if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -383,7 +383,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void callAfterRemove(ChannelHandlerContext ctx) {
|
private static void callAfterRemove(ChannelHandlerContext ctx) {
|
||||||
if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
|
if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -425,7 +425,6 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public synchronized <T extends ChannelHandler> T get(Class<T> handlerType) {
|
public synchronized <T extends ChannelHandler> T get(Class<T> handlerType) {
|
||||||
ChannelHandlerContext ctx = getContext(handlerType);
|
ChannelHandlerContext ctx = getContext(handlerType);
|
||||||
if (ctx == null) {
|
if (ctx == null) {
|
||||||
@ -586,7 +585,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
if (e instanceof UpstreamMessageEvent) {
|
if (e instanceof UpstreamMessageEvent) {
|
||||||
throw new IllegalArgumentException("cannot send an upstream event to downstream");
|
throw new IllegalArgumentException("cannot send an upstream event to downstream");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
((ChannelDownstreamHandler) ctx.getHandler()).handleDownstream(ctx, e);
|
((ChannelDownstreamHandler) ctx.getHandler()).handleDownstream(ctx, e);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
@ -631,11 +630,11 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
|
|
||||||
return realCtx;
|
return realCtx;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelFuture execute(Runnable task) {
|
public ChannelFuture execute(Runnable task) {
|
||||||
return getSink().execute(this, task);
|
return getSink().execute(this, task);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void notifyHandlerException(ChannelEvent e, Throwable t) {
|
protected void notifyHandlerException(ChannelEvent e, Throwable t) {
|
||||||
if (e instanceof ExceptionEvent) {
|
if (e instanceof ExceptionEvent) {
|
||||||
if (logger.isWarnEnabled()) {
|
if (logger.isWarnEnabled()) {
|
||||||
@ -803,15 +802,15 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
if (logger.isWarnEnabled()) {
|
if (logger.isWarnEnabled()) {
|
||||||
logger.warn("Not attached yet; discarding: " + e);
|
logger.warn("Not attached yet; discarding: " + e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void exceptionCaught(ChannelPipeline pipeline,
|
public void exceptionCaught(ChannelPipeline pipeline,
|
||||||
ChannelEvent e, ChannelPipelineException cause) throws Exception {
|
ChannelEvent e, ChannelPipelineException cause) throws Exception {
|
||||||
throw cause;
|
throw cause;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ChannelFuture execute(ChannelPipeline pipeline, Runnable task) {
|
public ChannelFuture execute(ChannelPipeline pipeline, Runnable task) {
|
||||||
if (logger.isWarnEnabled()) {
|
if (logger.isWarnEnabled()) {
|
||||||
logger.warn("Not attached yet; rejecting: " + task);
|
logger.warn("Not attached yet; rejecting: " + task);
|
||||||
|
@ -30,7 +30,7 @@ import org.jboss.netty.util.internal.ConversionUtil;
|
|||||||
* disabled dynamic insertion and removal of {@link ChannelHandler}s.
|
* disabled dynamic insertion and removal of {@link ChannelHandler}s.
|
||||||
* An attempt to insert, remove, or replace a handler in this pipeline will
|
* An attempt to insert, remove, or replace a handler in this pipeline will
|
||||||
* trigger an {@link UnsupportedOperationException}.
|
* trigger an {@link UnsupportedOperationException}.
|
||||||
*
|
*
|
||||||
* @deprecated use {@link DefaultChannelPipeline}
|
* @deprecated use {@link DefaultChannelPipeline}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@ -99,7 +99,7 @@ public class StaticChannelPipeline implements ChannelPipeline {
|
|||||||
public ChannelFuture execute(Runnable task) {
|
public ChannelFuture execute(Runnable task) {
|
||||||
return getSink().execute(this, task);
|
return getSink().execute(this, task);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Channel getChannel() {
|
public Channel getChannel() {
|
||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
@ -179,7 +179,7 @@ public class StaticChannelPipeline implements ChannelPipeline {
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void callBeforeAdd(ChannelHandlerContext ctx) {
|
private static void callBeforeAdd(ChannelHandlerContext ctx) {
|
||||||
if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
|
if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -196,7 +196,7 @@ public class StaticChannelPipeline implements ChannelPipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void callAfterAdd(ChannelHandlerContext ctx) {
|
private static void callAfterAdd(ChannelHandlerContext ctx) {
|
||||||
if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
|
if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -228,7 +228,7 @@ public class StaticChannelPipeline implements ChannelPipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void callBeforeRemove(ChannelHandlerContext ctx) {
|
private static void callBeforeRemove(ChannelHandlerContext ctx) {
|
||||||
if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
|
if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -245,7 +245,7 @@ public class StaticChannelPipeline implements ChannelPipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void callAfterRemove(ChannelHandlerContext ctx) {
|
private static void callAfterRemove(ChannelHandlerContext ctx) {
|
||||||
if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
|
if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -279,7 +279,6 @@ public class StaticChannelPipeline implements ChannelPipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T extends ChannelHandler> T get(Class<T> handlerType) {
|
public <T extends ChannelHandler> T get(Class<T> handlerType) {
|
||||||
ChannelHandlerContext ctx = getContext(handlerType);
|
ChannelHandlerContext ctx = getContext(handlerType);
|
||||||
if (ctx == null) {
|
if (ctx == null) {
|
||||||
|
@ -315,7 +315,7 @@ public class DefaultChannelGroupFuture implements ChannelGroupFuture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkDeadLock() {
|
private static void checkDeadLock() {
|
||||||
if (DeadLockProofWorker.PARENT.get() != null) {
|
if (DeadLockProofWorker.PARENT.get() != null) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"await*() in I/O thread causes a dead lock or " +
|
"await*() in I/O thread causes a dead lock or " +
|
||||||
|
@ -85,7 +85,7 @@ final class LocalClientChannelSink extends AbstractChannelSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bind(DefaultLocalChannel channel, ChannelFuture future, LocalAddress localAddress) {
|
private static void bind(DefaultLocalChannel channel, ChannelFuture future, LocalAddress localAddress) {
|
||||||
try {
|
try {
|
||||||
if (!LocalChannelRegistry.register(localAddress, channel)) {
|
if (!LocalChannelRegistry.register(localAddress, channel)) {
|
||||||
throw new ChannelException("address already in use: " + localAddress);
|
throw new ChannelException("address already in use: " + localAddress);
|
||||||
|
@ -42,7 +42,7 @@ final class LocalServerChannelSink extends AbstractChannelSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleServerChannel(ChannelEvent e) {
|
private static void handleServerChannel(ChannelEvent e) {
|
||||||
if (!(e instanceof ChannelStateEvent)) {
|
if (!(e instanceof ChannelStateEvent)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ final class LocalServerChannelSink extends AbstractChannelSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleAcceptedChannel(ChannelEvent e) {
|
private static void handleAcceptedChannel(ChannelEvent e) {
|
||||||
if (e instanceof ChannelStateEvent) {
|
if (e instanceof ChannelStateEvent) {
|
||||||
ChannelStateEvent event = (ChannelStateEvent) e;
|
ChannelStateEvent event = (ChannelStateEvent) e;
|
||||||
DefaultLocalChannel channel = (DefaultLocalChannel) event.getChannel();
|
DefaultLocalChannel channel = (DefaultLocalChannel) event.getChannel();
|
||||||
@ -103,7 +103,7 @@ final class LocalServerChannelSink extends AbstractChannelSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bind(DefaultLocalServerChannel channel, ChannelFuture future, LocalAddress localAddress) {
|
private static void bind(DefaultLocalServerChannel channel, ChannelFuture future, LocalAddress localAddress) {
|
||||||
try {
|
try {
|
||||||
if (!LocalChannelRegistry.register(localAddress, channel)) {
|
if (!LocalChannelRegistry.register(localAddress, channel)) {
|
||||||
throw new ChannelException("address already in use: " + localAddress);
|
throw new ChannelException("address already in use: " + localAddress);
|
||||||
@ -122,7 +122,7 @@ final class LocalServerChannelSink extends AbstractChannelSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void close(DefaultLocalServerChannel channel, ChannelFuture future) {
|
private static void close(DefaultLocalServerChannel channel, ChannelFuture future) {
|
||||||
try {
|
try {
|
||||||
if (channel.setClosed()) {
|
if (channel.setClosed()) {
|
||||||
future.setSuccess();
|
future.setSuccess();
|
||||||
|
@ -15,17 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.jboss.netty.channel.socket.nio;
|
package org.jboss.netty.channel.socket.nio;
|
||||||
|
|
||||||
import static org.jboss.netty.channel.Channels.fireChannelInterestChanged;
|
import static org.jboss.netty.channel.Channels.*;
|
||||||
import org.jboss.netty.buffer.ChannelBuffer;
|
|
||||||
import org.jboss.netty.channel.AbstractChannel;
|
|
||||||
import org.jboss.netty.channel.Channel;
|
|
||||||
import org.jboss.netty.channel.ChannelFactory;
|
|
||||||
import org.jboss.netty.channel.ChannelPipeline;
|
|
||||||
import org.jboss.netty.channel.ChannelSink;
|
|
||||||
import org.jboss.netty.channel.MessageEvent;
|
|
||||||
import org.jboss.netty.channel.socket.nio.SocketSendBufferPool.SendBuffer;
|
|
||||||
import org.jboss.netty.util.internal.QueueFactory;
|
|
||||||
import org.jboss.netty.util.internal.ThreadLocalBoolean;
|
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.nio.channels.SelectableChannel;
|
import java.nio.channels.SelectableChannel;
|
||||||
@ -38,6 +28,17 @@ import java.util.concurrent.TimeUnit;
|
|||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import org.jboss.netty.buffer.ChannelBuffer;
|
||||||
|
import org.jboss.netty.channel.AbstractChannel;
|
||||||
|
import org.jboss.netty.channel.Channel;
|
||||||
|
import org.jboss.netty.channel.ChannelFactory;
|
||||||
|
import org.jboss.netty.channel.ChannelPipeline;
|
||||||
|
import org.jboss.netty.channel.ChannelSink;
|
||||||
|
import org.jboss.netty.channel.MessageEvent;
|
||||||
|
import org.jboss.netty.channel.socket.nio.SocketSendBufferPool.SendBuffer;
|
||||||
|
import org.jboss.netty.util.internal.QueueFactory;
|
||||||
|
import org.jboss.netty.util.internal.ThreadLocalBoolean;
|
||||||
|
|
||||||
abstract class AbstractNioChannel<C extends SelectableChannel & WritableByteChannel> extends AbstractChannel {
|
abstract class AbstractNioChannel<C extends SelectableChannel & WritableByteChannel> extends AbstractChannel {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -92,19 +93,19 @@ abstract class AbstractNioChannel<C extends SelectableChannel & WritableByteChan
|
|||||||
*/
|
*/
|
||||||
boolean inWriteNowLoop;
|
boolean inWriteNowLoop;
|
||||||
boolean writeSuspended;
|
boolean writeSuspended;
|
||||||
|
|
||||||
|
|
||||||
private volatile InetSocketAddress localAddress;
|
private volatile InetSocketAddress localAddress;
|
||||||
volatile InetSocketAddress remoteAddress;
|
volatile InetSocketAddress remoteAddress;
|
||||||
|
|
||||||
final C channel;
|
final C channel;
|
||||||
|
|
||||||
protected AbstractNioChannel(Integer id, Channel parent, ChannelFactory factory, ChannelPipeline pipeline, ChannelSink sink, AbstractNioWorker worker, C ch) {
|
protected AbstractNioChannel(Integer id, Channel parent, ChannelFactory factory, ChannelPipeline pipeline, ChannelSink sink, AbstractNioWorker worker, C ch) {
|
||||||
super(id, parent, factory, pipeline, sink);
|
super(id, parent, factory, pipeline, sink);
|
||||||
this.worker = worker;
|
this.worker = worker;
|
||||||
this.channel = ch;
|
this.channel = ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AbstractNioChannel(
|
protected AbstractNioChannel(
|
||||||
Channel parent, ChannelFactory factory,
|
Channel parent, ChannelFactory factory,
|
||||||
ChannelPipeline pipeline, ChannelSink sink, AbstractNioWorker worker, C ch) {
|
ChannelPipeline pipeline, ChannelSink sink, AbstractNioWorker worker, C ch) {
|
||||||
@ -116,19 +117,18 @@ abstract class AbstractNioChannel<C extends SelectableChannel & WritableByteChan
|
|||||||
/**
|
/**
|
||||||
* Return the {@link AbstractNioWorker} that handle the IO of the
|
* Return the {@link AbstractNioWorker} that handle the IO of the
|
||||||
* {@link AbstractNioChannel}
|
* {@link AbstractNioChannel}
|
||||||
*
|
*
|
||||||
* @return worker
|
* @return worker
|
||||||
*/
|
*/
|
||||||
public AbstractNioWorker getWorker() {
|
public AbstractNioWorker getWorker() {
|
||||||
return worker;
|
return worker;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InetSocketAddress getLocalAddress() {
|
public InetSocketAddress getLocalAddress() {
|
||||||
InetSocketAddress localAddress = this.localAddress;
|
InetSocketAddress localAddress = this.localAddress;
|
||||||
if (localAddress == null) {
|
if (localAddress == null) {
|
||||||
try {
|
try {
|
||||||
this.localAddress = localAddress =
|
this.localAddress = localAddress = getLocalSocketAddress();
|
||||||
(InetSocketAddress) getLocalSocketAddress();
|
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
// Sometimes fails on a closed socket in Windows.
|
// Sometimes fails on a closed socket in Windows.
|
||||||
return null;
|
return null;
|
||||||
@ -142,7 +142,7 @@ abstract class AbstractNioChannel<C extends SelectableChannel & WritableByteChan
|
|||||||
if (remoteAddress == null) {
|
if (remoteAddress == null) {
|
||||||
try {
|
try {
|
||||||
this.remoteAddress = remoteAddress =
|
this.remoteAddress = remoteAddress =
|
||||||
(InetSocketAddress) getRemoteSocketAddress();
|
getRemoteSocketAddress();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
// Sometimes fails on a closed socket in Windows.
|
// Sometimes fails on a closed socket in Windows.
|
||||||
return null;
|
return null;
|
||||||
@ -150,9 +150,9 @@ abstract class AbstractNioChannel<C extends SelectableChannel & WritableByteChan
|
|||||||
}
|
}
|
||||||
return remoteAddress;
|
return remoteAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract NioChannelConfig getConfig();
|
public abstract NioChannelConfig getConfig();
|
||||||
|
|
||||||
int getRawInterestOps() {
|
int getRawInterestOps() {
|
||||||
return super.getInterestOps();
|
return super.getInterestOps();
|
||||||
}
|
}
|
||||||
@ -161,7 +161,7 @@ abstract class AbstractNioChannel<C extends SelectableChannel & WritableByteChan
|
|||||||
super.setInterestOpsNow(interestOps);
|
super.setInterestOpsNow(interestOps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getInterestOps() {
|
public int getInterestOps() {
|
||||||
if (!isOpen()) {
|
if (!isOpen()) {
|
||||||
@ -192,16 +192,16 @@ abstract class AbstractNioChannel<C extends SelectableChannel & WritableByteChan
|
|||||||
|
|
||||||
return interestOps;
|
return interestOps;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean setClosed() {
|
protected boolean setClosed() {
|
||||||
return super.setClosed();
|
return super.setClosed();
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract InetSocketAddress getLocalSocketAddress() throws Exception;
|
abstract InetSocketAddress getLocalSocketAddress() throws Exception;
|
||||||
|
|
||||||
abstract InetSocketAddress getRemoteSocketAddress() throws Exception;
|
abstract InetSocketAddress getRemoteSocketAddress() throws Exception;
|
||||||
|
|
||||||
private final class WriteRequestQueue implements BlockingQueue<MessageEvent> {
|
private final class WriteRequestQueue implements BlockingQueue<MessageEvent> {
|
||||||
private final ThreadLocalBoolean notifying = new ThreadLocalBoolean();
|
private final ThreadLocalBoolean notifying = new ThreadLocalBoolean();
|
||||||
|
|
||||||
@ -260,7 +260,7 @@ abstract class AbstractNioChannel<C extends SelectableChannel & WritableByteChan
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
queue.clear();
|
queue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean add(MessageEvent e) {
|
public boolean add(MessageEvent e) {
|
||||||
|
@ -45,7 +45,7 @@ class DefaultNioDatagramChannelConfig extends DefaultDatagramChannelConfig
|
|||||||
private volatile int writeBufferLowWaterMark = 32 * 1024;
|
private volatile int writeBufferLowWaterMark = 32 * 1024;
|
||||||
private volatile int writeSpinCount = 16;
|
private volatile int writeSpinCount = 16;
|
||||||
private final DatagramChannel channel;
|
private final DatagramChannel channel;
|
||||||
|
|
||||||
DefaultNioDatagramChannelConfig(DatagramChannel channel) {
|
DefaultNioDatagramChannelConfig(DatagramChannel channel) {
|
||||||
super(channel.socket());
|
super(channel.socket());
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
@ -142,7 +142,7 @@ class DefaultNioDatagramChannelConfig extends DefaultDatagramChannelConfig
|
|||||||
}
|
}
|
||||||
this.writeSpinCount = writeSpinCount;
|
this.writeSpinCount = writeSpinCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setNetworkInterface(NetworkInterface networkInterface) {
|
public void setNetworkInterface(NetworkInterface networkInterface) {
|
||||||
if (DetectionUtil.javaVersion() < 7) {
|
if (DetectionUtil.javaVersion() < 7) {
|
||||||
@ -162,7 +162,7 @@ class DefaultNioDatagramChannelConfig extends DefaultDatagramChannelConfig
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
return (NetworkInterface) channel.getOption(StandardSocketOptions.IP_MULTICAST_IF);
|
return channel.getOption(StandardSocketOptions.IP_MULTICAST_IF);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new ChannelException(e);
|
throw new ChannelException(e);
|
||||||
}
|
}
|
||||||
@ -175,7 +175,7 @@ class DefaultNioDatagramChannelConfig extends DefaultDatagramChannelConfig
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
return (int) channel.getOption(StandardSocketOptions.IP_MULTICAST_TTL);
|
return channel.getOption(StandardSocketOptions.IP_MULTICAST_TTL);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new ChannelException(e);
|
throw new ChannelException(e);
|
||||||
}
|
}
|
||||||
@ -193,9 +193,9 @@ class DefaultNioDatagramChannelConfig extends DefaultDatagramChannelConfig
|
|||||||
throw new ChannelException(e);
|
throw new ChannelException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InetAddress getInterface() {
|
public InetAddress getInterface() {
|
||||||
NetworkInterface inf = getNetworkInterface();
|
NetworkInterface inf = getNetworkInterface();
|
||||||
@ -225,7 +225,7 @@ class DefaultNioDatagramChannelConfig extends DefaultDatagramChannelConfig
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
return (Boolean) channel.getOption(StandardSocketOptions.IP_MULTICAST_LOOP);
|
return channel.getOption(StandardSocketOptions.IP_MULTICAST_LOOP);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new ChannelException(e);
|
throw new ChannelException(e);
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ class NioClientSocketPipelineSink extends AbstractNioChannelSink {
|
|||||||
|
|
||||||
this.workerPool = workerPool;
|
this.workerPool = workerPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void eventSunk(
|
public void eventSunk(
|
||||||
ChannelPipeline pipeline, ChannelEvent e) throws Exception {
|
ChannelPipeline pipeline, ChannelEvent e) throws Exception {
|
||||||
if (e instanceof ChannelStateEvent) {
|
if (e instanceof ChannelStateEvent) {
|
||||||
@ -117,7 +117,7 @@ class NioClientSocketPipelineSink extends AbstractNioChannelSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bind(
|
private static void bind(
|
||||||
NioClientSocketChannel channel, ChannelFuture future,
|
NioClientSocketChannel channel, ChannelFuture future,
|
||||||
SocketAddress localAddress) {
|
SocketAddress localAddress) {
|
||||||
try {
|
try {
|
||||||
@ -158,7 +158,7 @@ class NioClientSocketPipelineSink extends AbstractNioChannelSink {
|
|||||||
channel.worker.close(channel, succeededFuture(channel));
|
channel.worker.close(channel, succeededFuture(channel));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Boss nextBoss() {
|
Boss nextBoss() {
|
||||||
return bosses[Math.abs(
|
return bosses[Math.abs(
|
||||||
bossIndex.getAndIncrement() % bosses.length)];
|
bossIndex.getAndIncrement() % bosses.length)];
|
||||||
@ -175,10 +175,10 @@ class NioClientSocketPipelineSink extends AbstractNioChannelSink {
|
|||||||
private final AtomicBoolean wakenUp = new AtomicBoolean();
|
private final AtomicBoolean wakenUp = new AtomicBoolean();
|
||||||
private final Object startStopLock = new Object();
|
private final Object startStopLock = new Object();
|
||||||
private final Queue<Runnable> registerTaskQueue = QueueFactory.createQueue(Runnable.class);
|
private final Queue<Runnable> registerTaskQueue = QueueFactory.createQueue(Runnable.class);
|
||||||
private final int subId;;
|
private final int subId;
|
||||||
|
|
||||||
Boss(int subId) {
|
Boss(int subId) {
|
||||||
this.subId = subId;
|
this.subId = subId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void register(NioClientSocketChannel channel) {
|
void register(NioClientSocketChannel channel) {
|
||||||
@ -199,7 +199,7 @@ class NioClientSocketPipelineSink extends AbstractNioChannelSink {
|
|||||||
boolean success = false;
|
boolean success = false;
|
||||||
try {
|
try {
|
||||||
DeadLockProofWorker.start(bossExecutor,
|
DeadLockProofWorker.start(bossExecutor,
|
||||||
new ThreadRenamingRunnable(this,
|
new ThreadRenamingRunnable(this,
|
||||||
"New I/O client boss #" + id + '-' + subId));
|
"New I/O client boss #" + id + '-' + subId));
|
||||||
|
|
||||||
success = true;
|
success = true;
|
||||||
|
@ -15,15 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.jboss.netty.channel.socket.nio;
|
package org.jboss.netty.channel.socket.nio;
|
||||||
|
|
||||||
import static org.jboss.netty.channel.Channels.fireChannelOpen;
|
import static org.jboss.netty.channel.Channels.*;
|
||||||
import org.jboss.netty.channel.ChannelException;
|
|
||||||
import org.jboss.netty.channel.ChannelFactory;
|
|
||||||
import org.jboss.netty.channel.ChannelFuture;
|
|
||||||
import org.jboss.netty.channel.ChannelPipeline;
|
|
||||||
import org.jboss.netty.channel.ChannelSink;
|
|
||||||
import org.jboss.netty.channel.Channels;
|
|
||||||
import org.jboss.netty.channel.socket.DatagramChannelConfig;
|
|
||||||
import org.jboss.netty.util.internal.DetectionUtil;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
@ -39,6 +31,15 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jboss.netty.channel.ChannelException;
|
||||||
|
import org.jboss.netty.channel.ChannelFactory;
|
||||||
|
import org.jboss.netty.channel.ChannelFuture;
|
||||||
|
import org.jboss.netty.channel.ChannelPipeline;
|
||||||
|
import org.jboss.netty.channel.ChannelSink;
|
||||||
|
import org.jboss.netty.channel.Channels;
|
||||||
|
import org.jboss.netty.channel.socket.DatagramChannelConfig;
|
||||||
|
import org.jboss.netty.util.internal.DetectionUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides an NIO based {@link org.jboss.netty.channel.socket.DatagramChannel}.
|
* Provides an NIO based {@link org.jboss.netty.channel.socket.DatagramChannel}.
|
||||||
*/
|
*/
|
||||||
@ -53,13 +54,13 @@ public final class NioDatagramChannel extends AbstractNioChannel<DatagramChannel
|
|||||||
INET,
|
INET,
|
||||||
INET6
|
INET6
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link DatagramChannelConfig}.
|
* The {@link DatagramChannelConfig}.
|
||||||
*/
|
*/
|
||||||
private final NioDatagramChannelConfig config;
|
private final NioDatagramChannelConfig config;
|
||||||
private Map<InetAddress, List<MembershipKey>> memberships;
|
private Map<InetAddress, List<MembershipKey>> memberships;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use {@link #NioDatagramChannel(ChannelFactory, ChannelPipeline, ChannelSink, NioDatagramWorker, ProtocolFamily)}
|
* Use {@link #NioDatagramChannel(ChannelFactory, ChannelPipeline, ChannelSink, NioDatagramWorker, ProtocolFamily)}
|
||||||
*/
|
*/
|
||||||
@ -69,13 +70,13 @@ public final class NioDatagramChannel extends AbstractNioChannel<DatagramChannel
|
|||||||
final NioDatagramWorker worker) {
|
final NioDatagramWorker worker) {
|
||||||
this(factory, pipeline, sink, worker, null);
|
this(factory, pipeline, sink, worker, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
NioDatagramChannel(final ChannelFactory factory,
|
NioDatagramChannel(final ChannelFactory factory,
|
||||||
final ChannelPipeline pipeline, final ChannelSink sink,
|
final ChannelPipeline pipeline, final ChannelSink sink,
|
||||||
final NioDatagramWorker worker, ProtocolFamily family) {
|
final NioDatagramWorker worker, ProtocolFamily family) {
|
||||||
super(null, factory, pipeline, sink, worker, openNonBlockingChannel(family));
|
super(null, factory, pipeline, sink, worker, openNonBlockingChannel(family));
|
||||||
config = new DefaultNioDatagramChannelConfig(channel);
|
config = new DefaultNioDatagramChannelConfig(channel);
|
||||||
|
|
||||||
fireChannelOpen(this);
|
fireChannelOpen(this);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -83,7 +84,7 @@ public final class NioDatagramChannel extends AbstractNioChannel<DatagramChannel
|
|||||||
private static DatagramChannel openNonBlockingChannel(ProtocolFamily family) {
|
private static DatagramChannel openNonBlockingChannel(ProtocolFamily family) {
|
||||||
try {
|
try {
|
||||||
final DatagramChannel channel;
|
final DatagramChannel channel;
|
||||||
|
|
||||||
// check if we are on java 7 or if the family was not specified
|
// check if we are on java 7 or if the family was not specified
|
||||||
if (DetectionUtil.javaVersion() < 7 || family == null) {
|
if (DetectionUtil.javaVersion() < 7 || family == null) {
|
||||||
channel = DatagramChannel.open();
|
channel = DatagramChannel.open();
|
||||||
@ -102,7 +103,7 @@ public final class NioDatagramChannel extends AbstractNioChannel<DatagramChannel
|
|||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
channel.configureBlocking(false);
|
channel.configureBlocking(false);
|
||||||
return channel;
|
return channel;
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
@ -116,7 +117,7 @@ public final class NioDatagramChannel extends AbstractNioChannel<DatagramChannel
|
|||||||
public NioDatagramWorker getWorker() {
|
public NioDatagramWorker getWorker() {
|
||||||
return (NioDatagramWorker) super.getWorker();
|
return (NioDatagramWorker) super.getWorker();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBound() {
|
public boolean isBound() {
|
||||||
return isOpen() && channel.socket().isBound();
|
return isOpen() && channel.socket().isBound();
|
||||||
}
|
}
|
||||||
@ -130,6 +131,7 @@ public final class NioDatagramChannel extends AbstractNioChannel<DatagramChannel
|
|||||||
return super.setClosed();
|
return super.setClosed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public NioDatagramChannelConfig getConfig() {
|
public NioDatagramChannelConfig getConfig() {
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
@ -139,7 +141,7 @@ public final class NioDatagramChannel extends AbstractNioChannel<DatagramChannel
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public ChannelFuture joinGroup(InetAddress multicastAddress) {
|
public ChannelFuture joinGroup(InetAddress multicastAddress) {
|
||||||
try {
|
try {
|
||||||
return joinGroup(multicastAddress, NetworkInterface.getByInetAddress(getLocalAddress().getAddress()), null);
|
return joinGroup(multicastAddress, NetworkInterface.getByInetAddress(getLocalAddress().getAddress()), null);
|
||||||
@ -148,7 +150,7 @@ public final class NioDatagramChannel extends AbstractNioChannel<DatagramChannel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ChannelFuture joinGroup(InetSocketAddress multicastAddress, NetworkInterface networkInterface) {
|
public ChannelFuture joinGroup(InetSocketAddress multicastAddress, NetworkInterface networkInterface) {
|
||||||
return joinGroup(multicastAddress.getAddress(), networkInterface, null);
|
return joinGroup(multicastAddress.getAddress(), networkInterface, null);
|
||||||
}
|
}
|
||||||
@ -163,11 +165,11 @@ public final class NioDatagramChannel extends AbstractNioChannel<DatagramChannel
|
|||||||
if (multicastAddress == null) {
|
if (multicastAddress == null) {
|
||||||
throw new NullPointerException("multicastAddress");
|
throw new NullPointerException("multicastAddress");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (networkInterface == null) {
|
if (networkInterface == null) {
|
||||||
throw new NullPointerException("networkInterface");
|
throw new NullPointerException("networkInterface");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
MembershipKey key;
|
MembershipKey key;
|
||||||
if (source == null) {
|
if (source == null) {
|
||||||
@ -179,7 +181,7 @@ public final class NioDatagramChannel extends AbstractNioChannel<DatagramChannel
|
|||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (memberships == null) {
|
if (memberships == null) {
|
||||||
memberships = new HashMap<InetAddress, List<MembershipKey>>();
|
memberships = new HashMap<InetAddress, List<MembershipKey>>();
|
||||||
|
|
||||||
}
|
}
|
||||||
List<MembershipKey> keys = memberships.get(multicastAddress);
|
List<MembershipKey> keys = memberships.get(multicastAddress);
|
||||||
if (keys == null) {
|
if (keys == null) {
|
||||||
@ -194,14 +196,14 @@ public final class NioDatagramChannel extends AbstractNioChannel<DatagramChannel
|
|||||||
}
|
}
|
||||||
return Channels.succeededFuture(this);
|
return Channels.succeededFuture(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelFuture leaveGroup(InetAddress multicastAddress) {
|
public ChannelFuture leaveGroup(InetAddress multicastAddress) {
|
||||||
try {
|
try {
|
||||||
return leaveGroup(multicastAddress, NetworkInterface.getByInetAddress(getLocalAddress().getAddress()), null);
|
return leaveGroup(multicastAddress, NetworkInterface.getByInetAddress(getLocalAddress().getAddress()), null);
|
||||||
} catch (SocketException e) {
|
} catch (SocketException e) {
|
||||||
return Channels.failedFuture(this, e);
|
return Channels.failedFuture(this, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelFuture leaveGroup(InetSocketAddress multicastAddress,
|
public ChannelFuture leaveGroup(InetSocketAddress multicastAddress,
|
||||||
@ -220,25 +222,25 @@ public final class NioDatagramChannel extends AbstractNioChannel<DatagramChannel
|
|||||||
if (multicastAddress == null) {
|
if (multicastAddress == null) {
|
||||||
throw new NullPointerException("multicastAddress");
|
throw new NullPointerException("multicastAddress");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (networkInterface == null) {
|
if (networkInterface == null) {
|
||||||
throw new NullPointerException("networkInterface");
|
throw new NullPointerException("networkInterface");
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (memberships != null) {
|
if (memberships != null) {
|
||||||
List<MembershipKey> keys = memberships.get(multicastAddress);
|
List<MembershipKey> keys = memberships.get(multicastAddress);
|
||||||
if (keys != null) {
|
if (keys != null) {
|
||||||
Iterator<MembershipKey> keyIt = keys.iterator();
|
Iterator<MembershipKey> keyIt = keys.iterator();
|
||||||
|
|
||||||
while (keyIt.hasNext()) {
|
while (keyIt.hasNext()) {
|
||||||
MembershipKey key = keyIt.next();
|
MembershipKey key = keyIt.next();
|
||||||
if (networkInterface.equals(key.networkInterface())) {
|
if (networkInterface.equals(key.networkInterface())) {
|
||||||
if (source == null && key.sourceAddress() == null || (source != null && source.equals(key.sourceAddress()))) {
|
if (source == null && key.sourceAddress() == null || source != null && source.equals(key.sourceAddress())) {
|
||||||
key.drop();
|
key.drop();
|
||||||
keyIt.remove();
|
keyIt.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (keys.isEmpty()) {
|
if (keys.isEmpty()) {
|
||||||
@ -250,7 +252,7 @@ public final class NioDatagramChannel extends AbstractNioChannel<DatagramChannel
|
|||||||
return Channels.succeededFuture(this);
|
return Channels.succeededFuture(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Block the given sourceToBlock address for the given multicastAddress on the given networkInterface
|
* Block the given sourceToBlock address for the given multicastAddress on the given networkInterface
|
||||||
*
|
*
|
||||||
@ -266,7 +268,7 @@ public final class NioDatagramChannel extends AbstractNioChannel<DatagramChannel
|
|||||||
if (sourceToBlock == null) {
|
if (sourceToBlock == null) {
|
||||||
throw new NullPointerException("sourceToBlock");
|
throw new NullPointerException("sourceToBlock");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (networkInterface == null) {
|
if (networkInterface == null) {
|
||||||
throw new NullPointerException("networkInterface");
|
throw new NullPointerException("networkInterface");
|
||||||
}
|
}
|
||||||
@ -285,11 +287,11 @@ public final class NioDatagramChannel extends AbstractNioChannel<DatagramChannel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Channels.succeededFuture(this);
|
return Channels.succeededFuture(this);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Block the given sourceToBlock address for the given multicastAddress
|
* Block the given sourceToBlock address for the given multicastAddress
|
||||||
*
|
*
|
||||||
|
@ -41,6 +41,5 @@ import org.jboss.netty.channel.socket.DatagramChannelConfig;
|
|||||||
* </table>
|
* </table>
|
||||||
*/
|
*/
|
||||||
public interface NioDatagramChannelConfig extends DatagramChannelConfig, NioChannelConfig {
|
public interface NioDatagramChannelConfig extends DatagramChannelConfig, NioChannelConfig {
|
||||||
|
// Tag interface
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import org.jboss.netty.channel.ChannelPipeline;
|
|||||||
import org.jboss.netty.channel.group.ChannelGroup;
|
import org.jboss.netty.channel.group.ChannelGroup;
|
||||||
import org.jboss.netty.channel.socket.DatagramChannel;
|
import org.jboss.netty.channel.socket.DatagramChannel;
|
||||||
import org.jboss.netty.channel.socket.DatagramChannelFactory;
|
import org.jboss.netty.channel.socket.DatagramChannelFactory;
|
||||||
|
import org.jboss.netty.channel.socket.Worker;
|
||||||
import org.jboss.netty.channel.socket.nio.NioDatagramChannel.ProtocolFamily;
|
import org.jboss.netty.channel.socket.nio.NioDatagramChannel.ProtocolFamily;
|
||||||
import org.jboss.netty.channel.socket.oio.OioDatagramChannelFactory;
|
import org.jboss.netty.channel.socket.oio.OioDatagramChannelFactory;
|
||||||
import org.jboss.netty.util.ExternalResourceReleasable;
|
import org.jboss.netty.util.ExternalResourceReleasable;
|
||||||
@ -80,26 +81,26 @@ public class NioDatagramChannelFactory implements DatagramChannelFactory {
|
|||||||
private final NioDatagramPipelineSink sink;
|
private final NioDatagramPipelineSink sink;
|
||||||
private final WorkerPool<NioDatagramWorker> workerPool;
|
private final WorkerPool<NioDatagramWorker> workerPool;
|
||||||
private final NioDatagramChannel.ProtocolFamily family;
|
private final NioDatagramChannel.ProtocolFamily family;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link NioDatagramChannelFactory} with a {@link Executors#newCachedThreadPool()}.
|
* Create a new {@link NioDatagramChannelFactory} with a {@link Executors#newCachedThreadPool()}.
|
||||||
*
|
*
|
||||||
* See {@link #NioDatagramChannelFactory(Executor)}
|
* See {@link #NioDatagramChannelFactory(Executor)}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public NioDatagramChannelFactory() {
|
public NioDatagramChannelFactory() {
|
||||||
this(Executors.newCachedThreadPool(), null);
|
this(Executors.newCachedThreadPool(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link NioDatagramChannelFactory} with a {@link Executors#newCachedThreadPool()}.
|
* Create a new {@link NioDatagramChannelFactory} with a {@link Executors#newCachedThreadPool()}.
|
||||||
*
|
*
|
||||||
* See {@link #NioDatagramChannelFactory(Executor)}
|
* See {@link #NioDatagramChannelFactory(Executor)}
|
||||||
*/
|
*/
|
||||||
public NioDatagramChannelFactory(ProtocolFamily family) {
|
public NioDatagramChannelFactory(ProtocolFamily family) {
|
||||||
this(Executors.newCachedThreadPool(), family);
|
this(Executors.newCachedThreadPool(), family);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance. Calling this constructor is same with calling
|
* Creates a new instance. Calling this constructor is same with calling
|
||||||
* {@link #NioDatagramChannelFactory(Executor, int)} with 2 * the number of
|
* {@link #NioDatagramChannelFactory(Executor, int)} with 2 * the number of
|
||||||
@ -116,7 +117,7 @@ public class NioDatagramChannelFactory implements DatagramChannelFactory {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance.
|
* Creates a new instance.
|
||||||
*
|
*
|
||||||
* @param workerExecutor
|
* @param workerExecutor
|
||||||
* the {@link Executor} which will execute the I/O worker threads
|
* the {@link Executor} which will execute the I/O worker threads
|
||||||
* @param workerCount
|
* @param workerCount
|
||||||
@ -137,7 +138,7 @@ public class NioDatagramChannelFactory implements DatagramChannelFactory {
|
|||||||
public NioDatagramChannelFactory(WorkerPool<NioDatagramWorker> workerPool) {
|
public NioDatagramChannelFactory(WorkerPool<NioDatagramWorker> workerPool) {
|
||||||
this(workerPool, null);
|
this(workerPool, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance. Calling this constructor is same with calling
|
* Creates a new instance. Calling this constructor is same with calling
|
||||||
* {@link #NioDatagramChannelFactory(Executor, int)} with 2 * the number of
|
* {@link #NioDatagramChannelFactory(Executor, int)} with 2 * the number of
|
||||||
@ -146,8 +147,8 @@ public class NioDatagramChannelFactory implements DatagramChannelFactory {
|
|||||||
*
|
*
|
||||||
* @param workerExecutor
|
* @param workerExecutor
|
||||||
* the {@link Executor} which will execute the I/O worker threads
|
* the {@link Executor} which will execute the I/O worker threads
|
||||||
* @param family
|
* @param family
|
||||||
* the {@link ProtocolFamily} to use. This should be used for UDP multicast.
|
* the {@link ProtocolFamily} to use. This should be used for UDP multicast.
|
||||||
* <strong>Be aware that this option is only considered when running on java7+</strong>
|
* <strong>Be aware that this option is only considered when running on java7+</strong>
|
||||||
*/
|
*/
|
||||||
public NioDatagramChannelFactory(final Executor workerExecutor, ProtocolFamily family) {
|
public NioDatagramChannelFactory(final Executor workerExecutor, ProtocolFamily family) {
|
||||||
@ -161,7 +162,7 @@ public class NioDatagramChannelFactory implements DatagramChannelFactory {
|
|||||||
* the {@link Executor} which will execute the I/O worker threads
|
* the {@link Executor} which will execute the I/O worker threads
|
||||||
* @param workerCount
|
* @param workerCount
|
||||||
* the maximum number of I/O worker threads
|
* the maximum number of I/O worker threads
|
||||||
* @param family
|
* @param family
|
||||||
* the {@link ProtocolFamily} to use. This should be used for UDP multicast.
|
* the {@link ProtocolFamily} to use. This should be used for UDP multicast.
|
||||||
* <strong>Be aware that this option is only considered when running on java7+</strong>
|
* <strong>Be aware that this option is only considered when running on java7+</strong>
|
||||||
*/
|
*/
|
||||||
@ -172,10 +173,10 @@ public class NioDatagramChannelFactory implements DatagramChannelFactory {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance.
|
* Creates a new instance.
|
||||||
*
|
*
|
||||||
* @param workerPool
|
* @param workerPool
|
||||||
* the {@link WorkerPool} which will be used to obtain the {@link Worker} that execute the I/O worker threads
|
* the {@link WorkerPool} which will be used to obtain the {@link Worker} that execute the I/O worker threads
|
||||||
* @param family
|
* @param family
|
||||||
* the {@link ProtocolFamily} to use. This should be used for UDP multicast.
|
* the {@link ProtocolFamily} to use. This should be used for UDP multicast.
|
||||||
* <strong>Be aware that this option is only considered when running on java7+</strong>
|
* <strong>Be aware that this option is only considered when running on java7+</strong>
|
||||||
*/
|
*/
|
||||||
@ -184,7 +185,7 @@ public class NioDatagramChannelFactory implements DatagramChannelFactory {
|
|||||||
this.family = family;
|
this.family = family;
|
||||||
sink = new NioDatagramPipelineSink(workerPool);
|
sink = new NioDatagramPipelineSink(workerPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DatagramChannel newChannel(final ChannelPipeline pipeline) {
|
public DatagramChannel newChannel(final ChannelPipeline pipeline) {
|
||||||
return new NioDatagramChannel(this, pipeline, sink, sink.nextWorker(), family);
|
return new NioDatagramChannel(this, pipeline, sink, sink.nextWorker(), family);
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ class NioDatagramPipelineSink extends AbstractNioChannelSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void close(NioDatagramChannel channel, ChannelFuture future) {
|
private static void close(NioDatagramChannel channel, ChannelFuture future) {
|
||||||
try {
|
try {
|
||||||
channel.getDatagramChannel().socket().close();
|
channel.getDatagramChannel().socket().close();
|
||||||
if (channel.setClosed()) {
|
if (channel.setClosed()) {
|
||||||
@ -120,7 +120,7 @@ class NioDatagramPipelineSink extends AbstractNioChannelSink {
|
|||||||
* Will bind the DatagramSocket to the passed-in address.
|
* Will bind the DatagramSocket to the passed-in address.
|
||||||
* Every call bind will spawn a new thread using the that basically in turn
|
* Every call bind will spawn a new thread using the that basically in turn
|
||||||
*/
|
*/
|
||||||
private void bind(final NioDatagramChannel channel,
|
private static void bind(final NioDatagramChannel channel,
|
||||||
final ChannelFuture future, final InetSocketAddress address) {
|
final ChannelFuture future, final InetSocketAddress address) {
|
||||||
boolean bound = false;
|
boolean bound = false;
|
||||||
boolean started = false;
|
boolean started = false;
|
||||||
@ -144,7 +144,7 @@ class NioDatagramPipelineSink extends AbstractNioChannelSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void connect(
|
private static void connect(
|
||||||
NioDatagramChannel channel, ChannelFuture future,
|
NioDatagramChannel channel, ChannelFuture future,
|
||||||
SocketAddress remoteAddress) {
|
SocketAddress remoteAddress) {
|
||||||
|
|
||||||
|
@ -21,8 +21,8 @@ import java.nio.channels.SelectionKey;
|
|||||||
import java.nio.channels.Selector;
|
import java.nio.channels.Selector;
|
||||||
import java.nio.channels.ServerSocketChannel;
|
import java.nio.channels.ServerSocketChannel;
|
||||||
import java.nio.channels.spi.SelectorProvider;
|
import java.nio.channels.spi.SelectorProvider;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@ -231,63 +231,89 @@ final class NioProviderMetadata {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class ConstraintLevelAutodetector {
|
private static int autodetect() {
|
||||||
|
final int constraintLevel;
|
||||||
|
ExecutorService executor = Executors.newCachedThreadPool();
|
||||||
|
boolean success;
|
||||||
|
long startTime;
|
||||||
|
int interestOps;
|
||||||
|
|
||||||
ConstraintLevelAutodetector() {
|
ServerSocketChannel ch = null;
|
||||||
super();
|
SelectorLoop loop = null;
|
||||||
}
|
|
||||||
|
|
||||||
int autodetect() {
|
try {
|
||||||
final int constraintLevel;
|
// Open a channel.
|
||||||
ExecutorService executor = Executors.newCachedThreadPool();
|
ch = ServerSocketChannel.open();
|
||||||
boolean success;
|
|
||||||
long startTime;
|
|
||||||
int interestOps;
|
|
||||||
|
|
||||||
ServerSocketChannel ch = null;
|
|
||||||
SelectorLoop loop = null;
|
|
||||||
|
|
||||||
|
// Configure the channel
|
||||||
try {
|
try {
|
||||||
// Open a channel.
|
ch.socket().bind(new InetSocketAddress(0));
|
||||||
ch = ServerSocketChannel.open();
|
ch.configureBlocking(false);
|
||||||
|
} catch (Throwable e) {
|
||||||
// Configure the channel
|
if (logger.isWarnEnabled()) {
|
||||||
try {
|
logger.warn("Failed to configure a temporary socket.", e);
|
||||||
ch.socket().bind(new InetSocketAddress(0));
|
|
||||||
ch.configureBlocking(false);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
if (logger.isWarnEnabled()) {
|
|
||||||
logger.warn("Failed to configure a temporary socket.", e);
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare the selector loop.
|
// Prepare the selector loop.
|
||||||
try {
|
try {
|
||||||
loop = new SelectorLoop();
|
loop = new SelectorLoop();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
if (logger.isWarnEnabled()) {
|
if (logger.isWarnEnabled()) {
|
||||||
logger.warn("Failed to open a temporary selector.", e);
|
logger.warn("Failed to open a temporary selector.", e);
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// Register the channel
|
// Register the channel
|
||||||
try {
|
try {
|
||||||
ch.register(loop.selector, 0);
|
ch.register(loop.selector, 0);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
if (logger.isWarnEnabled()) {
|
if (logger.isWarnEnabled()) {
|
||||||
logger.warn("Failed to register a temporary selector.", e);
|
logger.warn("Failed to register a temporary selector.", e);
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
SelectionKey key = ch.keyFor(loop.selector);
|
SelectionKey key = ch.keyFor(loop.selector);
|
||||||
|
|
||||||
// Start the selector loop.
|
// Start the selector loop.
|
||||||
executor.execute(loop);
|
executor.execute(loop);
|
||||||
|
|
||||||
// Level 0
|
// Level 0
|
||||||
|
success = true;
|
||||||
|
for (int i = 0; i < 10; i ++) {
|
||||||
|
|
||||||
|
// Increase the probability of calling interestOps
|
||||||
|
// while select() is running.
|
||||||
|
do {
|
||||||
|
while (!loop.selecting) {
|
||||||
|
Thread.yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait a little bit more.
|
||||||
|
try {
|
||||||
|
Thread.sleep(50);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
} while (!loop.selecting);
|
||||||
|
|
||||||
|
startTime = System.nanoTime();
|
||||||
|
key.interestOps(key.interestOps() | SelectionKey.OP_ACCEPT);
|
||||||
|
key.interestOps(key.interestOps() & ~SelectionKey.OP_ACCEPT);
|
||||||
|
|
||||||
|
if (System.nanoTime() - startTime >= 500000000L) {
|
||||||
|
success = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
constraintLevel = 0;
|
||||||
|
} else {
|
||||||
|
// Level 1
|
||||||
success = true;
|
success = true;
|
||||||
for (int i = 0; i < 10; i ++) {
|
for (int i = 0; i < 10; i ++) {
|
||||||
|
|
||||||
@ -307,104 +333,71 @@ final class NioProviderMetadata {
|
|||||||
} while (!loop.selecting);
|
} while (!loop.selecting);
|
||||||
|
|
||||||
startTime = System.nanoTime();
|
startTime = System.nanoTime();
|
||||||
key.interestOps(key.interestOps() | SelectionKey.OP_ACCEPT);
|
interestOps = key.interestOps();
|
||||||
key.interestOps(key.interestOps() & ~SelectionKey.OP_ACCEPT);
|
synchronized (loop) {
|
||||||
|
loop.selector.wakeup();
|
||||||
|
key.interestOps(interestOps | SelectionKey.OP_ACCEPT);
|
||||||
|
key.interestOps(interestOps & ~SelectionKey.OP_ACCEPT);
|
||||||
|
}
|
||||||
|
|
||||||
if (System.nanoTime() - startTime >= 500000000L) {
|
if (System.nanoTime() - startTime >= 500000000L) {
|
||||||
success = false;
|
success = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
constraintLevel = 0;
|
constraintLevel = 1;
|
||||||
} else {
|
} else {
|
||||||
// Level 1
|
constraintLevel = 2;
|
||||||
success = true;
|
|
||||||
for (int i = 0; i < 10; i ++) {
|
|
||||||
|
|
||||||
// Increase the probability of calling interestOps
|
|
||||||
// while select() is running.
|
|
||||||
do {
|
|
||||||
while (!loop.selecting) {
|
|
||||||
Thread.yield();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait a little bit more.
|
|
||||||
try {
|
|
||||||
Thread.sleep(50);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
} while (!loop.selecting);
|
|
||||||
|
|
||||||
startTime = System.nanoTime();
|
|
||||||
interestOps = key.interestOps();
|
|
||||||
synchronized (loop) {
|
|
||||||
loop.selector.wakeup();
|
|
||||||
key.interestOps(interestOps | SelectionKey.OP_ACCEPT);
|
|
||||||
key.interestOps(interestOps & ~SelectionKey.OP_ACCEPT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (System.nanoTime() - startTime >= 500000000L) {
|
|
||||||
success = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (success) {
|
|
||||||
constraintLevel = 1;
|
|
||||||
} else {
|
|
||||||
constraintLevel = 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
}
|
||||||
return -1;
|
} catch (Throwable e) {
|
||||||
} finally {
|
return -1;
|
||||||
if (ch != null) {
|
} finally {
|
||||||
try {
|
if (ch != null) {
|
||||||
ch.close();
|
try {
|
||||||
} catch (Throwable e) {
|
ch.close();
|
||||||
if (logger.isWarnEnabled()) {
|
} catch (Throwable e) {
|
||||||
logger.warn("Failed to close a temporary socket.", e);
|
if (logger.isWarnEnabled()) {
|
||||||
}
|
logger.warn("Failed to close a temporary socket.", e);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loop != null) {
|
|
||||||
loop.done = true;
|
|
||||||
try {
|
|
||||||
executor.shutdownNow();
|
|
||||||
} catch (NullPointerException ex) {
|
|
||||||
// Some JDK throws NPE here, but shouldn't.
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
for (;;) {
|
|
||||||
loop.selector.wakeup();
|
|
||||||
try {
|
|
||||||
if (executor.awaitTermination(1, TimeUnit.SECONDS)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
|
||||||
// Perhaps security exception.
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
loop.selector.close();
|
|
||||||
} catch (Throwable e) {
|
|
||||||
if (logger.isWarnEnabled()) {
|
|
||||||
logger.warn("Failed to close a temporary selector.", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return constraintLevel;
|
if (loop != null) {
|
||||||
|
loop.done = true;
|
||||||
|
try {
|
||||||
|
executor.shutdownNow();
|
||||||
|
} catch (NullPointerException ex) {
|
||||||
|
// Some JDK throws NPE here, but shouldn't.
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (;;) {
|
||||||
|
loop.selector.wakeup();
|
||||||
|
try {
|
||||||
|
if (executor.awaitTermination(1, TimeUnit.SECONDS)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
// Perhaps security exception.
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
loop.selector.close();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
if (logger.isWarnEnabled()) {
|
||||||
|
logger.warn("Failed to close a temporary selector.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return constraintLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class SelectorLoop implements Runnable {
|
private static final class SelectorLoop implements Runnable {
|
||||||
@ -449,9 +442,7 @@ final class NioProviderMetadata {
|
|||||||
}
|
}
|
||||||
System.out.println();
|
System.out.println();
|
||||||
System.out.println("Hard-coded Constraint Level: " + CONSTRAINT_LEVEL);
|
System.out.println("Hard-coded Constraint Level: " + CONSTRAINT_LEVEL);
|
||||||
System.out.println(
|
System.out.println("Auto-detected Constraint Level: " + autodetect());
|
||||||
"Auto-detected Constraint Level: " +
|
|
||||||
new ConstraintLevelAutodetector().autodetect());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private NioProviderMetadata() {
|
private NioProviderMetadata() {
|
||||||
|
@ -47,7 +47,7 @@ class NioServerSocketPipelineSink extends AbstractNioChannelSink {
|
|||||||
|
|
||||||
static final InternalLogger logger =
|
static final InternalLogger logger =
|
||||||
InternalLoggerFactory.getInstance(NioServerSocketPipelineSink.class);
|
InternalLoggerFactory.getInstance(NioServerSocketPipelineSink.class);
|
||||||
|
|
||||||
final int id = nextId.incrementAndGet();
|
final int id = nextId.incrementAndGet();
|
||||||
|
|
||||||
private final WorkerPool<NioWorker> workerPool;
|
private final WorkerPool<NioWorker> workerPool;
|
||||||
@ -95,7 +95,7 @@ class NioServerSocketPipelineSink extends AbstractNioChannelSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleAcceptedSocket(ChannelEvent e) {
|
private static void handleAcceptedSocket(ChannelEvent e) {
|
||||||
if (e instanceof ChannelStateEvent) {
|
if (e instanceof ChannelStateEvent) {
|
||||||
ChannelStateEvent event = (ChannelStateEvent) e;
|
ChannelStateEvent event = (ChannelStateEvent) e;
|
||||||
NioSocketChannel channel = (NioSocketChannel) event.getChannel();
|
NioSocketChannel channel = (NioSocketChannel) event.getChannel();
|
||||||
@ -143,8 +143,8 @@ class NioServerSocketPipelineSink extends AbstractNioChannelSink {
|
|||||||
|
|
||||||
Executor bossExecutor =
|
Executor bossExecutor =
|
||||||
((NioServerSocketChannelFactory) channel.getFactory()).bossExecutor;
|
((NioServerSocketChannelFactory) channel.getFactory()).bossExecutor;
|
||||||
DeadLockProofWorker.start(bossExecutor,
|
DeadLockProofWorker.start(bossExecutor,
|
||||||
new ThreadRenamingRunnable(new Boss(channel),
|
new ThreadRenamingRunnable(new Boss(channel),
|
||||||
"New I/O server boss #" + id + " (" + channel + ')'));
|
"New I/O server boss #" + id + " (" + channel + ')'));
|
||||||
bossStarted = true;
|
bossStarted = true;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
@ -157,7 +157,7 @@ class NioServerSocketPipelineSink extends AbstractNioChannelSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void close(NioServerSocketChannel channel, ChannelFuture future) {
|
private static void close(NioServerSocketChannel channel, ChannelFuture future) {
|
||||||
boolean bound = channel.isBound();
|
boolean bound = channel.isBound();
|
||||||
try {
|
try {
|
||||||
if (channel.socket.isOpen()) {
|
if (channel.socket.isOpen()) {
|
||||||
@ -225,7 +225,7 @@ class NioServerSocketPipelineSink extends AbstractNioChannelSink {
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
try {
|
try {
|
||||||
if (selector.select(1000) > 0) {
|
if (selector.select(1000) > 0) {
|
||||||
// There was something selected if we reach this point, so clear
|
// There was something selected if we reach this point, so clear
|
||||||
// the selected keys
|
// the selected keys
|
||||||
selector.selectedKeys().clear();
|
selector.selectedKeys().clear();
|
||||||
}
|
}
|
||||||
@ -237,7 +237,7 @@ class NioServerSocketPipelineSink extends AbstractNioChannelSink {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
registerAcceptedChannel(acceptedSocket, currentThread);
|
registerAcceptedChannel(acceptedSocket, currentThread);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (SocketTimeoutException e) {
|
} catch (SocketTimeoutException e) {
|
||||||
|
@ -50,6 +50,7 @@ public class NioSocketChannel extends AbstractNioChannel<SocketChannel>
|
|||||||
return (NioWorker) super.getWorker();
|
return (NioWorker) super.getWorker();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public NioSocketChannelConfig getConfig() {
|
public NioSocketChannelConfig getConfig() {
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
@ -78,6 +79,7 @@ public class NioSocketChannel extends AbstractNioChannel<SocketChannel>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected boolean setClosed() {
|
protected boolean setClosed() {
|
||||||
state = ST_CLOSED;
|
state = ST_CLOSED;
|
||||||
return super.setClosed();
|
return super.setClosed();
|
||||||
@ -93,8 +95,8 @@ public class NioSocketChannel extends AbstractNioChannel<SocketChannel>
|
|||||||
InetSocketAddress getRemoteSocketAddress() throws Exception {
|
InetSocketAddress getRemoteSocketAddress() throws Exception {
|
||||||
return (InetSocketAddress) channel.socket().getRemoteSocketAddress();
|
return (InetSocketAddress) channel.socket().getRemoteSocketAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelFuture write(Object message, SocketAddress remoteAddress) {
|
public ChannelFuture write(Object message, SocketAddress remoteAddress) {
|
||||||
if (remoteAddress == null || remoteAddress.equals(getRemoteAddress())) {
|
if (remoteAddress == null || remoteAddress.equals(getRemoteAddress())) {
|
||||||
|
@ -32,7 +32,7 @@ abstract class AbstractOioChannel extends AbstractChannel {
|
|||||||
volatile InetSocketAddress remoteAddress;
|
volatile InetSocketAddress remoteAddress;
|
||||||
volatile Thread workerThread;
|
volatile Thread workerThread;
|
||||||
volatile Worker worker;
|
volatile Worker worker;
|
||||||
|
|
||||||
final Object interestOpsLock = new Object();
|
final Object interestOpsLock = new Object();
|
||||||
|
|
||||||
AbstractOioChannel(
|
AbstractOioChannel(
|
||||||
@ -42,7 +42,7 @@ abstract class AbstractOioChannel extends AbstractChannel {
|
|||||||
ChannelSink sink) {
|
ChannelSink sink) {
|
||||||
super(parent, factory, pipeline, sink);
|
super(parent, factory, pipeline, sink);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean setClosed() {
|
protected boolean setClosed() {
|
||||||
return super.setClosed();
|
return super.setClosed();
|
||||||
@ -61,25 +61,24 @@ abstract class AbstractOioChannel extends AbstractChannel {
|
|||||||
return super.write(message, remoteAddress);
|
return super.write(message, remoteAddress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean isBound() {
|
public boolean isBound() {
|
||||||
return isOpen() && isSocketBound();
|
return isOpen() && isSocketBound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean isConnected() {
|
public boolean isConnected() {
|
||||||
return isOpen() && isSocketConnected();
|
return isOpen() && isSocketConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public InetSocketAddress getLocalAddress() {
|
public InetSocketAddress getLocalAddress() {
|
||||||
InetSocketAddress localAddress = this.localAddress;
|
InetSocketAddress localAddress = this.localAddress;
|
||||||
if (localAddress == null) {
|
if (localAddress == null) {
|
||||||
try {
|
try {
|
||||||
this.localAddress = localAddress =
|
this.localAddress = localAddress = getLocalSocketAddress();
|
||||||
(InetSocketAddress) getLocalSocketAddress();
|
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
// Sometimes fails on a closed socket in Windows.
|
// Sometimes fails on a closed socket in Windows.
|
||||||
return null;
|
return null;
|
||||||
@ -88,13 +87,13 @@ abstract class AbstractOioChannel extends AbstractChannel {
|
|||||||
return localAddress;
|
return localAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public InetSocketAddress getRemoteAddress() {
|
public InetSocketAddress getRemoteAddress() {
|
||||||
InetSocketAddress remoteAddress = this.remoteAddress;
|
InetSocketAddress remoteAddress = this.remoteAddress;
|
||||||
if (remoteAddress == null) {
|
if (remoteAddress == null) {
|
||||||
try {
|
try {
|
||||||
this.remoteAddress = remoteAddress =
|
this.remoteAddress = remoteAddress =
|
||||||
(InetSocketAddress) getRemoteSocketAddress();
|
getRemoteSocketAddress();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
// Sometimes fails on a closed socket in Windows.
|
// Sometimes fails on a closed socket in Windows.
|
||||||
return null;
|
return null;
|
||||||
@ -102,17 +101,17 @@ abstract class AbstractOioChannel extends AbstractChannel {
|
|||||||
}
|
}
|
||||||
return remoteAddress;
|
return remoteAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract boolean isSocketBound();
|
abstract boolean isSocketBound();
|
||||||
|
|
||||||
abstract boolean isSocketConnected();
|
abstract boolean isSocketConnected();
|
||||||
|
|
||||||
abstract boolean isSocketClosed();
|
abstract boolean isSocketClosed();
|
||||||
|
|
||||||
abstract InetSocketAddress getLocalSocketAddress() throws Exception;
|
abstract InetSocketAddress getLocalSocketAddress() throws Exception;
|
||||||
|
|
||||||
abstract InetSocketAddress getRemoteSocketAddress() throws Exception;
|
abstract InetSocketAddress getRemoteSocketAddress() throws Exception;
|
||||||
|
|
||||||
abstract void closeSocket() throws IOException;
|
abstract void closeSocket() throws IOException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -50,25 +50,25 @@ class OioClientSocketPipelineSink extends AbstractOioChannelSink {
|
|||||||
switch (state) {
|
switch (state) {
|
||||||
case OPEN:
|
case OPEN:
|
||||||
if (Boolean.FALSE.equals(value)) {
|
if (Boolean.FALSE.equals(value)) {
|
||||||
OioWorker.close(channel, future);
|
AbstractOioWorker.close(channel, future);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BOUND:
|
case BOUND:
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
bind(channel, future, (SocketAddress) value);
|
bind(channel, future, (SocketAddress) value);
|
||||||
} else {
|
} else {
|
||||||
OioWorker.close(channel, future);
|
AbstractOioWorker.close(channel, future);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CONNECTED:
|
case CONNECTED:
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
connect(channel, future, (SocketAddress) value);
|
connect(channel, future, (SocketAddress) value);
|
||||||
} else {
|
} else {
|
||||||
OioWorker.close(channel, future);
|
AbstractOioWorker.close(channel, future);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case INTEREST_OPS:
|
case INTEREST_OPS:
|
||||||
OioWorker.setInterestOps(channel, future, ((Integer) value).intValue());
|
AbstractOioWorker.setInterestOps(channel, future, ((Integer) value).intValue());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (e instanceof MessageEvent) {
|
} else if (e instanceof MessageEvent) {
|
||||||
@ -78,7 +78,7 @@ class OioClientSocketPipelineSink extends AbstractOioChannelSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bind(
|
private static void bind(
|
||||||
OioClientSocketChannel channel, ChannelFuture future,
|
OioClientSocketChannel channel, ChannelFuture future,
|
||||||
SocketAddress localAddress) {
|
SocketAddress localAddress) {
|
||||||
try {
|
try {
|
||||||
@ -129,7 +129,7 @@ class OioClientSocketPipelineSink extends AbstractOioChannelSink {
|
|||||||
fireExceptionCaught(channel, t);
|
fireExceptionCaught(channel, t);
|
||||||
} finally {
|
} finally {
|
||||||
if (connected && !workerStarted) {
|
if (connected && !workerStarted) {
|
||||||
OioWorker.close(channel, future);
|
AbstractOioWorker.close(channel, future);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,14 +49,14 @@ class OioDatagramPipelineSink extends AbstractOioChannelSink {
|
|||||||
switch (state) {
|
switch (state) {
|
||||||
case OPEN:
|
case OPEN:
|
||||||
if (Boolean.FALSE.equals(value)) {
|
if (Boolean.FALSE.equals(value)) {
|
||||||
OioDatagramWorker.close(channel, future);
|
AbstractOioWorker.close(channel, future);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BOUND:
|
case BOUND:
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
bind(channel, future, (SocketAddress) value);
|
bind(channel, future, (SocketAddress) value);
|
||||||
} else {
|
} else {
|
||||||
OioDatagramWorker.close(channel, future);
|
AbstractOioWorker.close(channel, future);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CONNECTED:
|
case CONNECTED:
|
||||||
@ -67,7 +67,7 @@ class OioDatagramPipelineSink extends AbstractOioChannelSink {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case INTEREST_OPS:
|
case INTEREST_OPS:
|
||||||
OioDatagramWorker.setInterestOps(channel, future, ((Integer) value).intValue());
|
AbstractOioWorker.setInterestOps(channel, future, ((Integer) value).intValue());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (e instanceof MessageEvent) {
|
} else if (e instanceof MessageEvent) {
|
||||||
@ -102,7 +102,7 @@ class OioDatagramPipelineSink extends AbstractOioChannelSink {
|
|||||||
fireExceptionCaught(channel, t);
|
fireExceptionCaught(channel, t);
|
||||||
} finally {
|
} finally {
|
||||||
if (bound && !workerStarted) {
|
if (bound && !workerStarted) {
|
||||||
OioDatagramWorker.close(channel, future);
|
AbstractOioWorker.close(channel, future);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,7 +157,7 @@ class OioDatagramPipelineSink extends AbstractOioChannelSink {
|
|||||||
fireExceptionCaught(channel, t);
|
fireExceptionCaught(channel, t);
|
||||||
} finally {
|
} finally {
|
||||||
if (connected && !workerStarted) {
|
if (connected && !workerStarted) {
|
||||||
OioDatagramWorker.close(channel, future);
|
AbstractOioWorker.close(channel, future);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ class OioServerSocketPipelineSink extends AbstractOioChannelSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleAcceptedSocket(ChannelEvent e) {
|
private static void handleAcceptedSocket(ChannelEvent e) {
|
||||||
if (e instanceof ChannelStateEvent) {
|
if (e instanceof ChannelStateEvent) {
|
||||||
ChannelStateEvent event = (ChannelStateEvent) e;
|
ChannelStateEvent event = (ChannelStateEvent) e;
|
||||||
OioAcceptedSocketChannel channel =
|
OioAcceptedSocketChannel channel =
|
||||||
@ -96,17 +96,17 @@ class OioServerSocketPipelineSink extends AbstractOioChannelSink {
|
|||||||
switch (state) {
|
switch (state) {
|
||||||
case OPEN:
|
case OPEN:
|
||||||
if (Boolean.FALSE.equals(value)) {
|
if (Boolean.FALSE.equals(value)) {
|
||||||
OioWorker.close(channel, future);
|
AbstractOioWorker.close(channel, future);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BOUND:
|
case BOUND:
|
||||||
case CONNECTED:
|
case CONNECTED:
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
OioWorker.close(channel, future);
|
AbstractOioWorker.close(channel, future);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case INTEREST_OPS:
|
case INTEREST_OPS:
|
||||||
OioWorker.setInterestOps(channel, future, ((Integer) value).intValue());
|
AbstractOioWorker.setInterestOps(channel, future, ((Integer) value).intValue());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (e instanceof MessageEvent) {
|
} else if (e instanceof MessageEvent) {
|
||||||
@ -150,7 +150,7 @@ class OioServerSocketPipelineSink extends AbstractOioChannelSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void close(OioServerSocketChannel channel, ChannelFuture future) {
|
private static void close(OioServerSocketChannel channel, ChannelFuture future) {
|
||||||
boolean bound = channel.isBound();
|
boolean bound = channel.isBound();
|
||||||
try {
|
try {
|
||||||
channel.socket.close();
|
channel.socket.close();
|
||||||
|
@ -138,7 +138,7 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
|
SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
|
||||||
Date ifModifiedSinceDate = dateFormatter.parse(ifModifiedSince);
|
Date ifModifiedSinceDate = dateFormatter.parse(ifModifiedSince);
|
||||||
|
|
||||||
// Only compare up to the second because the datetime format we send to the client does not have milliseconds
|
// Only compare up to the second because the datetime format we send to the client does not have milliseconds
|
||||||
long ifModifiedSinceDateSeconds = ifModifiedSinceDate.getTime() / 1000;
|
long ifModifiedSinceDateSeconds = ifModifiedSinceDate.getTime() / 1000;
|
||||||
long fileLastModifiedSeconds = file.lastModified() / 1000;
|
long fileLastModifiedSeconds = file.lastModified() / 1000;
|
||||||
if (ifModifiedSinceDateSeconds == fileLastModifiedSeconds) {
|
if (ifModifiedSinceDateSeconds == fileLastModifiedSeconds) {
|
||||||
@ -146,7 +146,7 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RandomAccessFile raf;
|
RandomAccessFile raf;
|
||||||
try {
|
try {
|
||||||
raf = new RandomAccessFile(file, "r");
|
raf = new RandomAccessFile(file, "r");
|
||||||
@ -160,7 +160,7 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
setContentLength(response, fileLength);
|
setContentLength(response, fileLength);
|
||||||
setContentTypeHeader(response, file);
|
setContentTypeHeader(response, file);
|
||||||
setDateAndCacheHeaders(response, file);
|
setDateAndCacheHeaders(response, file);
|
||||||
|
|
||||||
Channel ch = e.getChannel();
|
Channel ch = e.getChannel();
|
||||||
|
|
||||||
// Write the initial line and the header.
|
// Write the initial line and the header.
|
||||||
@ -211,7 +211,7 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String sanitizeUri(String uri) {
|
private static String sanitizeUri(String uri) {
|
||||||
// Decode the path.
|
// Decode the path.
|
||||||
try {
|
try {
|
||||||
uri = URLDecoder.decode(uri, "UTF-8");
|
uri = URLDecoder.decode(uri, "UTF-8");
|
||||||
@ -238,7 +238,7 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
return System.getProperty("user.dir") + File.separator + uri;
|
return System.getProperty("user.dir") + File.separator + uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) {
|
private static void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) {
|
||||||
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, status);
|
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, status);
|
||||||
response.setHeader(CONTENT_TYPE, "text/plain; charset=UTF-8");
|
response.setHeader(CONTENT_TYPE, "text/plain; charset=UTF-8");
|
||||||
response.setContent(ChannelBuffers.copiedBuffer(
|
response.setContent(ChannelBuffers.copiedBuffer(
|
||||||
@ -248,44 +248,44 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
// Close the connection as soon as the error message is sent.
|
// Close the connection as soon as the error message is sent.
|
||||||
ctx.getChannel().write(response).addListener(ChannelFutureListener.CLOSE);
|
ctx.getChannel().write(response).addListener(ChannelFutureListener.CLOSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When file timestamp is the same as what the browser is sending up, send a "304 Not Modified"
|
* When file timestamp is the same as what the browser is sending up, send a "304 Not Modified"
|
||||||
*
|
*
|
||||||
* @param ctx
|
* @param ctx
|
||||||
* Context
|
* Context
|
||||||
*/
|
*/
|
||||||
private void sendNotModified(ChannelHandlerContext ctx) {
|
private static void sendNotModified(ChannelHandlerContext ctx) {
|
||||||
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.NOT_MODIFIED);
|
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.NOT_MODIFIED);
|
||||||
setDateHeader(response);
|
setDateHeader(response);
|
||||||
|
|
||||||
// Close the connection as soon as the error message is sent.
|
// Close the connection as soon as the error message is sent.
|
||||||
ctx.getChannel().write(response).addListener(ChannelFutureListener.CLOSE);
|
ctx.getChannel().write(response).addListener(ChannelFutureListener.CLOSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the Date header for the HTTP response
|
* Sets the Date header for the HTTP response
|
||||||
*
|
*
|
||||||
* @param response
|
* @param response
|
||||||
* HTTP response
|
* HTTP response
|
||||||
*/
|
*/
|
||||||
private void setDateHeader(HttpResponse response) {
|
private static void setDateHeader(HttpResponse response) {
|
||||||
SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
|
SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
|
||||||
dateFormatter.setTimeZone(TimeZone.getTimeZone(HTTP_DATE_GMT_TIMEZONE));
|
dateFormatter.setTimeZone(TimeZone.getTimeZone(HTTP_DATE_GMT_TIMEZONE));
|
||||||
|
|
||||||
Calendar time = new GregorianCalendar();
|
Calendar time = new GregorianCalendar();
|
||||||
response.setHeader(HttpHeaders.Names.DATE, dateFormatter.format(time.getTime()));
|
response.setHeader(HttpHeaders.Names.DATE, dateFormatter.format(time.getTime()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the Date and Cache headers for the HTTP Response
|
* Sets the Date and Cache headers for the HTTP Response
|
||||||
*
|
*
|
||||||
* @param response
|
* @param response
|
||||||
* HTTP response
|
* HTTP response
|
||||||
* @param fileToCache
|
* @param fileToCache
|
||||||
* file to extract content type
|
* file to extract content type
|
||||||
*/
|
*/
|
||||||
private void setDateAndCacheHeaders(HttpResponse response, File fileToCache) {
|
private static void setDateAndCacheHeaders(HttpResponse response, File fileToCache) {
|
||||||
SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
|
SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
|
||||||
dateFormatter.setTimeZone(TimeZone.getTimeZone(HTTP_DATE_GMT_TIMEZONE));
|
dateFormatter.setTimeZone(TimeZone.getTimeZone(HTTP_DATE_GMT_TIMEZONE));
|
||||||
|
|
||||||
@ -302,13 +302,13 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the content type header for the HTTP Response
|
* Sets the content type header for the HTTP Response
|
||||||
*
|
*
|
||||||
* @param response
|
* @param response
|
||||||
* HTTP response
|
* HTTP response
|
||||||
* @param file
|
* @param file
|
||||||
* file to extract content type
|
* file to extract content type
|
||||||
*/
|
*/
|
||||||
private void setContentTypeHeader(HttpResponse response, File file) {
|
private static void setContentTypeHeader(HttpResponse response, File file) {
|
||||||
MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();
|
MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();
|
||||||
response.setHeader(HttpHeaders.Names.CONTENT_TYPE, mimeTypesMap.getContentType(file.getPath()));
|
response.setHeader(HttpHeaders.Names.CONTENT_TYPE, mimeTypesMap.getContentType(file.getPath()));
|
||||||
}
|
}
|
||||||
|
@ -160,7 +160,7 @@ public class HttpSnoopServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void send100Continue(MessageEvent e) {
|
private static void send100Continue(MessageEvent e) {
|
||||||
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, CONTINUE);
|
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, CONTINUE);
|
||||||
e.getChannel().write(response);
|
e.getChannel().write(response);
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ import org.jboss.netty.logging.InternalLoggerFactory;
|
|||||||
import org.jboss.netty.util.CharsetUtil;
|
import org.jboss.netty.util.CharsetUtil;
|
||||||
|
|
||||||
public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||||
|
|
||||||
private static final InternalLogger logger =
|
private static final InternalLogger logger =
|
||||||
InternalLoggerFactory.getInstance(HttpUploadServerHandler.class);
|
InternalLoggerFactory.getInstance(HttpUploadServerHandler.class);
|
||||||
|
|
||||||
@ -87,6 +87,7 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
DiskAttribute.baseDirectory = null; // system temp directory
|
DiskAttribute.baseDirectory = null; // system temp directory
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)
|
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
if (decoder != null) {
|
if (decoder != null) {
|
||||||
@ -94,6 +95,7 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
||||||
if (!readingChunks) {
|
if (!readingChunks) {
|
||||||
// clean previous FileUpload if Any
|
// clean previous FileUpload if Any
|
||||||
@ -480,6 +482,7 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
e.getChannel().write(response);
|
e.getChannel().write(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
|
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
logger.error(responseContent.toString(), e.getCause());
|
logger.error(responseContent.toString(), e.getCause());
|
||||||
|
@ -71,12 +71,12 @@ public class AutobahnServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
|
|
||||||
// Handshake
|
// Handshake
|
||||||
WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
|
WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
|
||||||
this.getWebSocketLocation(req), null, false);
|
getWebSocketLocation(req), null, false);
|
||||||
this.handshaker = wsFactory.newHandshaker(req);
|
handshaker = wsFactory.newHandshaker(req);
|
||||||
if (this.handshaker == null) {
|
if (handshaker == null) {
|
||||||
wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.getChannel());
|
wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.getChannel());
|
||||||
} else {
|
} else {
|
||||||
this.handshaker.handshake(ctx.getChannel(), req).addListener(WebSocketServerHandshaker.HANDSHAKE_LISTENER);
|
handshaker.handshake(ctx.getChannel(), req).addListener(WebSocketServerHandshaker.HANDSHAKE_LISTENER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ public class AutobahnServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
|
|
||||||
|
|
||||||
if (frame instanceof CloseWebSocketFrame) {
|
if (frame instanceof CloseWebSocketFrame) {
|
||||||
this.handshaker.close(ctx.getChannel(), (CloseWebSocketFrame) frame);
|
handshaker.close(ctx.getChannel(), (CloseWebSocketFrame) frame);
|
||||||
} else if (frame instanceof PingWebSocketFrame) {
|
} else if (frame instanceof PingWebSocketFrame) {
|
||||||
ctx.getChannel().write(
|
ctx.getChannel().write(
|
||||||
new PongWebSocketFrame(frame.isFinalFragment(), frame.getRsv(), frame.getBinaryData()));
|
new PongWebSocketFrame(frame.isFinalFragment(), frame.getRsv(), frame.getBinaryData()));
|
||||||
@ -110,7 +110,7 @@ public class AutobahnServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendHttpResponse(ChannelHandlerContext ctx, HttpRequest req, HttpResponse res) {
|
private static void sendHttpResponse(ChannelHandlerContext ctx, HttpRequest req, HttpResponse res) {
|
||||||
// Generate an error page if response status code is not OK (200).
|
// Generate an error page if response status code is not OK (200).
|
||||||
if (res.getStatus().getCode() != 200) {
|
if (res.getStatus().getCode() != 200) {
|
||||||
res.setContent(ChannelBuffers.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8));
|
res.setContent(ChannelBuffers.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8));
|
||||||
@ -130,7 +130,7 @@ public class AutobahnServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
e.getChannel().close();
|
e.getChannel().close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getWebSocketLocation(HttpRequest req) {
|
private static String getWebSocketLocation(HttpRequest req) {
|
||||||
return "ws://" + req.getHeader(HttpHeaders.Names.HOST);
|
return "ws://" + req.getHeader(HttpHeaders.Names.HOST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,11 +61,11 @@ import org.jboss.netty.handler.codec.http.websocketx.WebSocketVersion;
|
|||||||
public class WebSocketClient {
|
public class WebSocketClient {
|
||||||
|
|
||||||
private final URI uri;
|
private final URI uri;
|
||||||
|
|
||||||
public WebSocketClient(URI uri) {
|
public WebSocketClient(URI uri) {
|
||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
ClientBootstrap bootstrap =
|
ClientBootstrap bootstrap =
|
||||||
new ClientBootstrap(
|
new ClientBootstrap(
|
||||||
@ -74,58 +74,58 @@ public class WebSocketClient {
|
|||||||
Executors.newCachedThreadPool()));
|
Executors.newCachedThreadPool()));
|
||||||
|
|
||||||
Channel ch = null;
|
Channel ch = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String protocol = uri.getScheme();
|
String protocol = uri.getScheme();
|
||||||
if (!protocol.equals("ws")) {
|
if (!protocol.equals("ws")) {
|
||||||
throw new IllegalArgumentException("Unsupported protocol: " + protocol);
|
throw new IllegalArgumentException("Unsupported protocol: " + protocol);
|
||||||
}
|
}
|
||||||
|
|
||||||
HashMap<String, String> customHeaders = new HashMap<String, String>();
|
HashMap<String, String> customHeaders = new HashMap<String, String>();
|
||||||
customHeaders.put("MyHeader", "MyValue");
|
customHeaders.put("MyHeader", "MyValue");
|
||||||
|
|
||||||
// Connect with V13 (RFC 6455 aka HyBi-17). You can change it to V08 or V00.
|
// Connect with V13 (RFC 6455 aka HyBi-17). You can change it to V08 or V00.
|
||||||
// If you change it to V00, ping is not supported and remember to change
|
// If you change it to V00, ping is not supported and remember to change
|
||||||
// HttpResponseDecoder to WebSocketHttpResponseDecoder in the pipeline.
|
// HttpResponseDecoder to WebSocketHttpResponseDecoder in the pipeline.
|
||||||
final WebSocketClientHandshaker handshaker =
|
final WebSocketClientHandshaker handshaker =
|
||||||
new WebSocketClientHandshakerFactory().newHandshaker(
|
new WebSocketClientHandshakerFactory().newHandshaker(
|
||||||
uri, WebSocketVersion.V13, null, false, customHeaders);
|
uri, WebSocketVersion.V13, null, false, customHeaders);
|
||||||
|
|
||||||
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
|
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
|
||||||
public ChannelPipeline getPipeline() throws Exception {
|
public ChannelPipeline getPipeline() throws Exception {
|
||||||
ChannelPipeline pipeline = Channels.pipeline();
|
ChannelPipeline pipeline = Channels.pipeline();
|
||||||
|
|
||||||
pipeline.addLast("decoder", new HttpResponseDecoder());
|
pipeline.addLast("decoder", new HttpResponseDecoder());
|
||||||
pipeline.addLast("encoder", new HttpRequestEncoder());
|
pipeline.addLast("encoder", new HttpRequestEncoder());
|
||||||
pipeline.addLast("ws-handler", new WebSocketClientHandler(handshaker));
|
pipeline.addLast("ws-handler", new WebSocketClientHandler(handshaker));
|
||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Connect
|
// Connect
|
||||||
System.out.println("WebSocket Client connecting");
|
System.out.println("WebSocket Client connecting");
|
||||||
ChannelFuture future =
|
ChannelFuture future =
|
||||||
bootstrap.connect(
|
bootstrap.connect(
|
||||||
new InetSocketAddress(uri.getHost(), uri.getPort()));
|
new InetSocketAddress(uri.getHost(), uri.getPort()));
|
||||||
future.awaitUninterruptibly().rethrowIfFailed();
|
future.syncUninterruptibly();
|
||||||
|
|
||||||
ch = future.getChannel();
|
ch = future.getChannel();
|
||||||
handshaker.handshake(ch).awaitUninterruptibly().rethrowIfFailed();
|
handshaker.handshake(ch).syncUninterruptibly();
|
||||||
|
|
||||||
// Send 10 messages and wait for responses
|
// Send 10 messages and wait for responses
|
||||||
System.out.println("WebSocket Client sending message");
|
System.out.println("WebSocket Client sending message");
|
||||||
for (int i = 0; i < 1000; i++) {
|
for (int i = 0; i < 1000; i++) {
|
||||||
ch.write(new TextWebSocketFrame("Message #" + i));
|
ch.write(new TextWebSocketFrame("Message #" + i));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ping
|
// Ping
|
||||||
System.out.println("WebSocket Client sending ping");
|
System.out.println("WebSocket Client sending ping");
|
||||||
ch.write(new PingWebSocketFrame(ChannelBuffers.copiedBuffer(new byte[]{1, 2, 3, 4, 5, 6})));
|
ch.write(new PingWebSocketFrame(ChannelBuffers.copiedBuffer(new byte[]{1, 2, 3, 4, 5, 6})));
|
||||||
|
|
||||||
// Close
|
// Close
|
||||||
System.out.println("WebSocket Client sending close");
|
System.out.println("WebSocket Client sending close");
|
||||||
ch.write(new CloseWebSocketFrame());
|
ch.write(new CloseWebSocketFrame());
|
||||||
|
|
||||||
// WebSocketClientHandler will close the connection when the server
|
// WebSocketClientHandler will close the connection when the server
|
||||||
// responds to the CloseWebSocketFrame.
|
// responds to the CloseWebSocketFrame.
|
||||||
ch.getCloseFuture().awaitUninterruptibly();
|
ch.getCloseFuture().awaitUninterruptibly();
|
||||||
|
@ -16,8 +16,9 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>This is an example web service client.
|
* <p>This is an example web service client.
|
||||||
* <p>To run this example, you must first start {@link WebSocketServer} and
|
* <p>To run this example, you must first start
|
||||||
* then {@link WebSocketClient}.
|
* {@link org.jboss.netty.example.http.websocketx.server.WebSocketServer} and then
|
||||||
|
* {@link org.jboss.netty.example.http.websocketx.client.WebSocketClient}.
|
||||||
*/
|
*/
|
||||||
package org.jboss.netty.example.http.websocketx.client;
|
package org.jboss.netty.example.http.websocketx.client;
|
||||||
|
|
||||||
|
@ -91,12 +91,12 @@ public class WebSocketServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
|
|
||||||
// Handshake
|
// Handshake
|
||||||
WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
|
WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
|
||||||
this.getWebSocketLocation(req), null, false);
|
getWebSocketLocation(req), null, false);
|
||||||
this.handshaker = wsFactory.newHandshaker(req);
|
handshaker = wsFactory.newHandshaker(req);
|
||||||
if (this.handshaker == null) {
|
if (handshaker == null) {
|
||||||
wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.getChannel());
|
wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.getChannel());
|
||||||
} else {
|
} else {
|
||||||
this.handshaker.handshake(ctx.getChannel(), req).addListener(WebSocketServerHandshaker.HANDSHAKE_LISTENER);
|
handshaker.handshake(ctx.getChannel(), req).addListener(WebSocketServerHandshaker.HANDSHAKE_LISTENER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ public class WebSocketServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
|
|
||||||
// Check for closing frame
|
// Check for closing frame
|
||||||
if (frame instanceof CloseWebSocketFrame) {
|
if (frame instanceof CloseWebSocketFrame) {
|
||||||
this.handshaker.close(ctx.getChannel(), (CloseWebSocketFrame) frame);
|
handshaker.close(ctx.getChannel(), (CloseWebSocketFrame) frame);
|
||||||
return;
|
return;
|
||||||
} else if (frame instanceof PingWebSocketFrame) {
|
} else if (frame instanceof PingWebSocketFrame) {
|
||||||
ctx.getChannel().write(new PongWebSocketFrame(frame.getBinaryData()));
|
ctx.getChannel().write(new PongWebSocketFrame(frame.getBinaryData()));
|
||||||
@ -122,7 +122,7 @@ public class WebSocketServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
ctx.getChannel().write(new TextWebSocketFrame(request.toUpperCase()));
|
ctx.getChannel().write(new TextWebSocketFrame(request.toUpperCase()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendHttpResponse(ChannelHandlerContext ctx, HttpRequest req, HttpResponse res) {
|
private static void sendHttpResponse(ChannelHandlerContext ctx, HttpRequest req, HttpResponse res) {
|
||||||
// Generate an error page if response status code is not OK (200).
|
// Generate an error page if response status code is not OK (200).
|
||||||
if (res.getStatus().getCode() != 200) {
|
if (res.getStatus().getCode() != 200) {
|
||||||
res.setContent(ChannelBuffers.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8));
|
res.setContent(ChannelBuffers.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8));
|
||||||
@ -142,7 +142,7 @@ public class WebSocketServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
e.getChannel().close();
|
e.getChannel().close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getWebSocketLocation(HttpRequest req) {
|
private static String getWebSocketLocation(HttpRequest req) {
|
||||||
return "ws://" + req.getHeader(HttpHeaders.Names.HOST) + WEBSOCKET_PATH;
|
return "ws://" + req.getHeader(HttpHeaders.Names.HOST) + WEBSOCKET_PATH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,12 +91,12 @@ public class WebSocketSslServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
|
|
||||||
// Handshake
|
// Handshake
|
||||||
WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
|
WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
|
||||||
this.getWebSocketLocation(req), null, false);
|
getWebSocketLocation(req), null, false);
|
||||||
this.handshaker = wsFactory.newHandshaker(req);
|
handshaker = wsFactory.newHandshaker(req);
|
||||||
if (this.handshaker == null) {
|
if (handshaker == null) {
|
||||||
wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.getChannel());
|
wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.getChannel());
|
||||||
} else {
|
} else {
|
||||||
this.handshaker.handshake(ctx.getChannel(), req).addListener(WebSocketServerHandshaker.HANDSHAKE_LISTENER);
|
handshaker.handshake(ctx.getChannel(), req).addListener(WebSocketServerHandshaker.HANDSHAKE_LISTENER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ public class WebSocketSslServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
|
|
||||||
// Check for closing frame
|
// Check for closing frame
|
||||||
if (frame instanceof CloseWebSocketFrame) {
|
if (frame instanceof CloseWebSocketFrame) {
|
||||||
this.handshaker.close(ctx.getChannel(), (CloseWebSocketFrame) frame);
|
handshaker.close(ctx.getChannel(), (CloseWebSocketFrame) frame);
|
||||||
return;
|
return;
|
||||||
} else if (frame instanceof PingWebSocketFrame) {
|
} else if (frame instanceof PingWebSocketFrame) {
|
||||||
ctx.getChannel().write(new PongWebSocketFrame(frame.getBinaryData()));
|
ctx.getChannel().write(new PongWebSocketFrame(frame.getBinaryData()));
|
||||||
@ -122,7 +122,7 @@ public class WebSocketSslServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
ctx.getChannel().write(new TextWebSocketFrame(request.toUpperCase()));
|
ctx.getChannel().write(new TextWebSocketFrame(request.toUpperCase()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendHttpResponse(ChannelHandlerContext ctx, HttpRequest req, HttpResponse res) {
|
private static void sendHttpResponse(ChannelHandlerContext ctx, HttpRequest req, HttpResponse res) {
|
||||||
// Generate an error page if response status code is not OK (200).
|
// Generate an error page if response status code is not OK (200).
|
||||||
if (res.getStatus().getCode() != 200) {
|
if (res.getStatus().getCode() != 200) {
|
||||||
res.setContent(ChannelBuffers.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8));
|
res.setContent(ChannelBuffers.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8));
|
||||||
@ -142,7 +142,7 @@ public class WebSocketSslServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
e.getChannel().close();
|
e.getChannel().close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getWebSocketLocation(HttpRequest req) {
|
private static String getWebSocketLocation(HttpRequest req) {
|
||||||
return "wss://" + req.getHeader(HttpHeaders.Names.HOST) + WEBSOCKET_PATH;
|
return "wss://" + req.getHeader(HttpHeaders.Names.HOST) + WEBSOCKET_PATH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ public class PortUnificationServerHandler extends FrameDecoder {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isHttp(int magic1, int magic2) {
|
private static boolean isHttp(int magic1, int magic2) {
|
||||||
return
|
return
|
||||||
magic1 == 'G' && magic2 == 'E' || // GET
|
magic1 == 'G' && magic2 == 'E' || // GET
|
||||||
magic1 == 'P' && magic2 == 'O' || // POST
|
magic1 == 'P' && magic2 == 'O' || // POST
|
||||||
@ -115,7 +115,7 @@ public class PortUnificationServerHandler extends FrameDecoder {
|
|||||||
magic1 == 'C' && magic2 == 'O'; // CONNECT
|
magic1 == 'C' && magic2 == 'O'; // CONNECT
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isFactorial(int magic1) {
|
private static boolean isFactorial(int magic1) {
|
||||||
return magic1 == 'F';
|
return magic1 == 'F';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,12 +123,10 @@ abstract class AbstractCodecEmbedder<E> implements CodecEmbedder<E> {
|
|||||||
return productQueue.isEmpty();
|
return productQueue.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public final E poll() {
|
public final E poll() {
|
||||||
return (E) productQueue.poll();
|
return (E) productQueue.poll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public final E peek() {
|
public final E peek() {
|
||||||
return (E) productQueue.peek();
|
return (E) productQueue.peek();
|
||||||
}
|
}
|
||||||
@ -217,7 +215,7 @@ abstract class AbstractCodecEmbedder<E> implements CodecEmbedder<E> {
|
|||||||
|
|
||||||
throw new CodecEmbedderException(actualCause);
|
throw new CodecEmbedderException(actualCause);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelFuture execute(ChannelPipeline pipeline, Runnable task) {
|
public ChannelFuture execute(ChannelPipeline pipeline, Runnable task) {
|
||||||
try {
|
try {
|
||||||
task.run();
|
task.run();
|
||||||
|
@ -30,6 +30,7 @@ import org.jboss.netty.channel.Channels;
|
|||||||
import org.jboss.netty.channel.ExceptionEvent;
|
import org.jboss.netty.channel.ExceptionEvent;
|
||||||
import org.jboss.netty.channel.MessageEvent;
|
import org.jboss.netty.channel.MessageEvent;
|
||||||
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
||||||
|
import org.jboss.netty.handler.codec.replay.ReplayingDecoder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decodes the received {@link ChannelBuffer}s into a meaningful frame object.
|
* Decodes the received {@link ChannelBuffer}s into a meaningful frame object.
|
||||||
@ -207,12 +208,12 @@ public abstract class FrameDecoder extends SimpleChannelUpstreamHandler {
|
|||||||
callDecode(ctx, e.getChannel(), input, e.getRemoteAddress());
|
callDecode(ctx, e.getChannel(), input, e.getRemoteAddress());
|
||||||
if (input.readable()) {
|
if (input.readable()) {
|
||||||
// seems like there is something readable left in the input buffer. So create the cumulation buffer and copy the input into it
|
// seems like there is something readable left in the input buffer. So create the cumulation buffer and copy the input into it
|
||||||
(this.cumulation = newCumulationBuffer(ctx, input.readableBytes())).writeBytes(input);
|
(cumulation = newCumulationBuffer(ctx, input.readableBytes())).writeBytes(input);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert cumulation.readable();
|
assert cumulation.readable();
|
||||||
boolean fit = false;
|
boolean fit = false;
|
||||||
|
|
||||||
int readable = input.readableBytes();
|
int readable = input.readableBytes();
|
||||||
int writable = cumulation.writableBytes();
|
int writable = cumulation.writableBytes();
|
||||||
int w = writable - readable;
|
int w = writable - readable;
|
||||||
@ -228,28 +229,28 @@ public abstract class FrameDecoder extends SimpleChannelUpstreamHandler {
|
|||||||
// ok the input fit into the cumulation buffer
|
// ok the input fit into the cumulation buffer
|
||||||
fit = true;
|
fit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ChannelBuffer buf;
|
ChannelBuffer buf;
|
||||||
if (fit) {
|
if (fit) {
|
||||||
// the input fit in the cumulation buffer so copy it over
|
// the input fit in the cumulation buffer so copy it over
|
||||||
buf = this.cumulation;
|
buf = cumulation;
|
||||||
buf.writeBytes(input);
|
buf.writeBytes(input);
|
||||||
} else {
|
} else {
|
||||||
// wrap the cumulation and input
|
// wrap the cumulation and input
|
||||||
buf = ChannelBuffers.wrappedBuffer(cumulation, input);
|
buf = ChannelBuffers.wrappedBuffer(cumulation, input);
|
||||||
this.cumulation = buf;
|
cumulation = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
callDecode(ctx, e.getChannel(), buf, e.getRemoteAddress());
|
callDecode(ctx, e.getChannel(), buf, e.getRemoteAddress());
|
||||||
if (!buf.readable()) {
|
if (!buf.readable()) {
|
||||||
// nothing readable left so reset the state
|
// nothing readable left so reset the state
|
||||||
this.cumulation = null;
|
cumulation = null;
|
||||||
} else {
|
} else {
|
||||||
// create a new buffer and copy the readable buffer into it
|
// create a new buffer and copy the readable buffer into it
|
||||||
this.cumulation = newCumulationBuffer(ctx, buf.readableBytes());
|
cumulation = newCumulationBuffer(ctx, buf.readableBytes());
|
||||||
this.cumulation.writeBytes(buf);
|
cumulation.writeBytes(buf);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -312,7 +312,7 @@ public abstract class AbstractDiskHttpData extends AbstractHttpData {
|
|||||||
* @return the array of bytes
|
* @return the array of bytes
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private byte[] readFrom(File src) throws IOException {
|
private static byte[] readFrom(File src) throws IOException {
|
||||||
long srcsize = src.length();
|
long srcsize = src.length();
|
||||||
if (srcsize > Integer.MAX_VALUE) {
|
if (srcsize > Integer.MAX_VALUE) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
|
@ -32,6 +32,7 @@ final class CaseIgnoringComparator implements Comparator<String>, Serializable {
|
|||||||
return o1.compareToIgnoreCase(o2);
|
return o1.compareToIgnoreCase(o2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("static-method")
|
||||||
private Object readResolve() {
|
private Object readResolve() {
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
@ -194,7 +194,7 @@ public class CookieDecoder {
|
|||||||
return cookies;
|
return cookies;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void extractKeyValuePairs(
|
private static void extractKeyValuePairs(
|
||||||
String header, List<String> names, List<String> values) {
|
String header, List<String> names, List<String> values) {
|
||||||
Matcher m = PATTERN.matcher(header);
|
Matcher m = PATTERN.matcher(header);
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
@ -243,7 +243,7 @@ public class CookieDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String decodeValue(String value) {
|
private static String decodeValue(String value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ public class HttpContentCompressor extends HttpContentEncoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ZlibWrapper determineWrapper(String acceptEncoding) {
|
private static ZlibWrapper determineWrapper(String acceptEncoding) {
|
||||||
float starQ = -1.0f;
|
float starQ = -1.0f;
|
||||||
float gzipQ = -1.0f;
|
float gzipQ = -1.0f;
|
||||||
float deflateQ = -1.0f;
|
float deflateQ = -1.0f;
|
||||||
|
@ -368,10 +368,10 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder<HttpMessageDec
|
|||||||
if (msg instanceof HttpResponse) {
|
if (msg instanceof HttpResponse) {
|
||||||
HttpResponse res = (HttpResponse) msg;
|
HttpResponse res = (HttpResponse) msg;
|
||||||
int code = res.getStatus().getCode();
|
int code = res.getStatus().getCode();
|
||||||
|
|
||||||
// Correctly handle return codes of 1xx.
|
// Correctly handle return codes of 1xx.
|
||||||
//
|
//
|
||||||
// See:
|
// See:
|
||||||
// - http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html Section 4.4
|
// - http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html Section 4.4
|
||||||
// - https://github.com/netty/netty/issues/222
|
// - https://github.com/netty/netty/issues/222
|
||||||
if (code >= 100 && code < 200) {
|
if (code >= 100 && code < 200) {
|
||||||
@ -405,7 +405,7 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder<HttpMessageDec
|
|||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void skipControlCharacters(ChannelBuffer buffer) {
|
private static void skipControlCharacters(ChannelBuffer buffer) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char c = (char) buffer.readUnsignedByte();
|
char c = (char) buffer.readUnsignedByte();
|
||||||
if (!Character.isISOControl(c) &&
|
if (!Character.isISOControl(c) &&
|
||||||
@ -557,7 +557,7 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder<HttpMessageDec
|
|||||||
protected abstract boolean isDecodingRequest();
|
protected abstract boolean isDecodingRequest();
|
||||||
protected abstract HttpMessage createMessage(String[] initialLine) throws Exception;
|
protected abstract HttpMessage createMessage(String[] initialLine) throws Exception;
|
||||||
|
|
||||||
private int getChunkSize(String hex) {
|
private static int getChunkSize(String hex) {
|
||||||
hex = hex.trim();
|
hex = hex.trim();
|
||||||
for (int i = 0; i < hex.length(); i ++) {
|
for (int i = 0; i < hex.length(); i ++) {
|
||||||
char c = hex.charAt(i);
|
char c = hex.charAt(i);
|
||||||
@ -570,7 +570,7 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder<HttpMessageDec
|
|||||||
return Integer.parseInt(hex, 16);
|
return Integer.parseInt(hex, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String readLine(ChannelBuffer buffer, int maxLineLength) throws TooLongFrameException {
|
private static String readLine(ChannelBuffer buffer, int maxLineLength) throws TooLongFrameException {
|
||||||
StringBuilder sb = new StringBuilder(64);
|
StringBuilder sb = new StringBuilder(64);
|
||||||
int lineLength = 0;
|
int lineLength = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -598,7 +598,7 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder<HttpMessageDec
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String[] splitInitialLine(String sb) {
|
private static String[] splitInitialLine(String sb) {
|
||||||
int aStart;
|
int aStart;
|
||||||
int aEnd;
|
int aEnd;
|
||||||
int bStart;
|
int bStart;
|
||||||
@ -621,7 +621,7 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder<HttpMessageDec
|
|||||||
cStart < cEnd? sb.substring(cStart, cEnd) : "" };
|
cStart < cEnd? sb.substring(cStart, cEnd) : "" };
|
||||||
}
|
}
|
||||||
|
|
||||||
private String[] splitHeader(String sb) {
|
private static String[] splitHeader(String sb) {
|
||||||
final int length = sb.length();
|
final int length = sb.length();
|
||||||
int nameStart;
|
int nameStart;
|
||||||
int nameEnd;
|
int nameEnd;
|
||||||
@ -659,7 +659,7 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder<HttpMessageDec
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private int findNonWhitespace(String sb, int offset) {
|
private static int findNonWhitespace(String sb, int offset) {
|
||||||
int result;
|
int result;
|
||||||
for (result = offset; result < sb.length(); result ++) {
|
for (result = offset; result < sb.length(); result ++) {
|
||||||
if (!Character.isWhitespace(sb.charAt(result))) {
|
if (!Character.isWhitespace(sb.charAt(result))) {
|
||||||
@ -669,7 +669,7 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder<HttpMessageDec
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int findWhitespace(String sb, int offset) {
|
private static int findWhitespace(String sb, int offset) {
|
||||||
int result;
|
int result;
|
||||||
for (result = offset; result < sb.length(); result ++) {
|
for (result = offset; result < sb.length(); result ++) {
|
||||||
if (Character.isWhitespace(sb.charAt(result))) {
|
if (Character.isWhitespace(sb.charAt(result))) {
|
||||||
@ -679,7 +679,7 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder<HttpMessageDec
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int findEndOfString(String sb) {
|
private static int findEndOfString(String sb) {
|
||||||
int result;
|
int result;
|
||||||
for (result = sb.length(); result > 0; result --) {
|
for (result = sb.length(); result > 0; result --) {
|
||||||
if (!Character.isWhitespace(sb.charAt(result - 1))) {
|
if (!Character.isWhitespace(sb.charAt(result - 1))) {
|
||||||
|
@ -136,7 +136,7 @@ public abstract class HttpMessageEncoder extends OneToOneEncoder {
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeHeaders(ChannelBuffer buf, HttpMessage message) {
|
private static void encodeHeaders(ChannelBuffer buf, HttpMessage message) {
|
||||||
try {
|
try {
|
||||||
for (Map.Entry<String, String> h: message.getHeaders()) {
|
for (Map.Entry<String, String> h: message.getHeaders()) {
|
||||||
encodeHeader(buf, h.getKey(), h.getValue());
|
encodeHeader(buf, h.getKey(), h.getValue());
|
||||||
@ -146,7 +146,7 @@ public abstract class HttpMessageEncoder extends OneToOneEncoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeTrailingHeaders(ChannelBuffer buf, HttpChunkTrailer trailer) {
|
private static void encodeTrailingHeaders(ChannelBuffer buf, HttpChunkTrailer trailer) {
|
||||||
try {
|
try {
|
||||||
for (Map.Entry<String, String> h: trailer.getHeaders()) {
|
for (Map.Entry<String, String> h: trailer.getHeaders()) {
|
||||||
encodeHeader(buf, h.getKey(), h.getValue());
|
encodeHeader(buf, h.getKey(), h.getValue());
|
||||||
@ -156,7 +156,7 @@ public abstract class HttpMessageEncoder extends OneToOneEncoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeHeader(ChannelBuffer buf, String header, String value)
|
private static void encodeHeader(ChannelBuffer buf, String header, String value)
|
||||||
throws UnsupportedEncodingException {
|
throws UnsupportedEncodingException {
|
||||||
buf.writeBytes(header.getBytes("ASCII"));
|
buf.writeBytes(header.getBytes("ASCII"));
|
||||||
buf.writeByte(COLON);
|
buf.writeByte(COLON);
|
||||||
|
@ -867,7 +867,7 @@ public class HttpPostRequestDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the next Multipart Delimiter
|
* Find the next Multipart Delimiter
|
||||||
* @param delimiter delimiter to find
|
* @param delimiter delimiter to find
|
||||||
@ -1272,7 +1272,7 @@ public class HttpPostRequestDecoder {
|
|||||||
undecodedChunk.readerIndex(readerIndex);
|
undecodedChunk.readerIndex(readerIndex);
|
||||||
throw new NotEnoughDataDecoderException();
|
throw new NotEnoughDataDecoderException();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read a FileUpload data as Byte (Binary) and add the bytes directly to the
|
* Read a FileUpload data as Byte (Binary) and add the bytes directly to the
|
||||||
* FileUpload. If the delimiter is found, the FileUpload is completed.
|
* FileUpload. If the delimiter is found, the FileUpload is completed.
|
||||||
@ -1482,7 +1482,7 @@ public class HttpPostRequestDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the field value from a Multipart request
|
* Load the field value from a Multipart request
|
||||||
* @throws NotEnoughDataDecoderException Need more chunks
|
* @throws NotEnoughDataDecoderException Need more chunks
|
||||||
@ -1691,12 +1691,12 @@ public class HttpPostRequestDecoder {
|
|||||||
throw new NotEnoughDataDecoderException(e);
|
throw new NotEnoughDataDecoderException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clean the String from any unallowed character
|
* Clean the String from any unallowed character
|
||||||
* @return the cleaned String
|
* @return the cleaned String
|
||||||
*/
|
*/
|
||||||
private String cleanString(String field) {
|
private static String cleanString(String field) {
|
||||||
StringBuilder sb = new StringBuilder(field.length());
|
StringBuilder sb = new StringBuilder(field.length());
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (i = 0; i < field.length(); i ++) {
|
for (i = 0; i < field.length(); i ++) {
|
||||||
@ -1752,7 +1752,7 @@ public class HttpPostRequestDecoder {
|
|||||||
* @param sb
|
* @param sb
|
||||||
* @return the array of 2 Strings
|
* @return the array of 2 Strings
|
||||||
*/
|
*/
|
||||||
private String[] splitHeaderContentType(String sb) {
|
private static String[] splitHeaderContentType(String sb) {
|
||||||
int size = sb.length();
|
int size = sb.length();
|
||||||
int aStart;
|
int aStart;
|
||||||
int aEnd;
|
int aEnd;
|
||||||
@ -1778,7 +1778,7 @@ public class HttpPostRequestDecoder {
|
|||||||
* @return an array of String where rank 0 is the name of the header, follows by several
|
* @return an array of String where rank 0 is the name of the header, follows by several
|
||||||
* values that were separated by ';' or ','
|
* values that were separated by ';' or ','
|
||||||
*/
|
*/
|
||||||
private String[] splitMultipartHeader(String sb) {
|
private static String[] splitMultipartHeader(String sb) {
|
||||||
ArrayList<String> headers = new ArrayList<String>(1);
|
ArrayList<String> headers = new ArrayList<String>(1);
|
||||||
int nameStart;
|
int nameStart;
|
||||||
int nameEnd;
|
int nameEnd;
|
||||||
|
@ -56,11 +56,11 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
|||||||
/**
|
/**
|
||||||
* InterfaceHttpData for Body (without encoding)
|
* InterfaceHttpData for Body (without encoding)
|
||||||
*/
|
*/
|
||||||
private List<InterfaceHttpData> bodyListDatas;
|
private final List<InterfaceHttpData> bodyListDatas;
|
||||||
/**
|
/**
|
||||||
* The final Multipart List of InterfaceHttpData including encoding
|
* The final Multipart List of InterfaceHttpData including encoding
|
||||||
*/
|
*/
|
||||||
private List<InterfaceHttpData> multipartHttpDatas;
|
private final List<InterfaceHttpData> multipartHttpDatas;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does this request is a Multipart request
|
* Does this request is a Multipart request
|
||||||
@ -201,7 +201,7 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
|||||||
*
|
*
|
||||||
* @return a newly generated Delimiter (either for DATA or MIXED)
|
* @return a newly generated Delimiter (either for DATA or MIXED)
|
||||||
*/
|
*/
|
||||||
private String getNewMultipartDelimiter() {
|
private static String getNewMultipartDelimiter() {
|
||||||
// construct a generated delimiter
|
// construct a generated delimiter
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
return Long.toHexString(random.nextLong()).toLowerCase();
|
return Long.toHexString(random.nextLong()).toLowerCase();
|
||||||
|
@ -24,6 +24,7 @@ import org.jboss.netty.util.CharsetUtil;
|
|||||||
*
|
*
|
||||||
* The default {@link WebSocketFrame} implementation.
|
* The default {@link WebSocketFrame} implementation.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public class DefaultWebSocketFrame implements WebSocketFrame {
|
public class DefaultWebSocketFrame implements WebSocketFrame {
|
||||||
|
|
||||||
private int type;
|
private int type;
|
||||||
|
@ -23,6 +23,7 @@ import org.jboss.netty.buffer.ChannelBuffers;
|
|||||||
*
|
*
|
||||||
* A Web Socket frame that represents either text or binary data.
|
* A Web Socket frame that represents either text or binary data.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public interface WebSocketFrame {
|
public interface WebSocketFrame {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,6 +33,7 @@ import org.jboss.netty.handler.codec.replay.VoidEnum;
|
|||||||
* @apiviz.landmark
|
* @apiviz.landmark
|
||||||
* @apiviz.uses org.jboss.netty.handler.codec.http.websocket.WebSocketFrame
|
* @apiviz.uses org.jboss.netty.handler.codec.http.websocket.WebSocketFrame
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public class WebSocketFrameDecoder extends ReplayingDecoder<VoidEnum> {
|
public class WebSocketFrameDecoder extends ReplayingDecoder<VoidEnum> {
|
||||||
|
|
||||||
public static final int DEFAULT_MAX_FRAME_SIZE = 16384;
|
public static final int DEFAULT_MAX_FRAME_SIZE = 16384;
|
||||||
|
@ -17,8 +17,8 @@ package org.jboss.netty.handler.codec.http.websocket;
|
|||||||
|
|
||||||
import org.jboss.netty.buffer.ChannelBuffer;
|
import org.jboss.netty.buffer.ChannelBuffer;
|
||||||
import org.jboss.netty.channel.Channel;
|
import org.jboss.netty.channel.Channel;
|
||||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
|
||||||
import org.jboss.netty.channel.ChannelHandler.Sharable;
|
import org.jboss.netty.channel.ChannelHandler.Sharable;
|
||||||
|
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||||
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
|
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,6 +32,7 @@ import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
|
|||||||
* @apiviz.landmark
|
* @apiviz.landmark
|
||||||
* @apiviz.uses org.jboss.netty.handler.codec.http.websocket.WebSocketFrame
|
* @apiviz.uses org.jboss.netty.handler.codec.http.websocket.WebSocketFrame
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
@Sharable
|
@Sharable
|
||||||
public class WebSocketFrameEncoder extends OneToOneEncoder {
|
public class WebSocketFrameEncoder extends OneToOneEncoder {
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ public class WebSocket08FrameDecoder extends ReplayingDecoder<WebSocket08FrameDe
|
|||||||
private UTF8Output fragmentedFramesText;
|
private UTF8Output fragmentedFramesText;
|
||||||
private int fragmentedFramesCount;
|
private int fragmentedFramesCount;
|
||||||
|
|
||||||
private long maxFramePayloadLength;
|
private final long maxFramePayloadLength;
|
||||||
private boolean frameFinalFlag;
|
private boolean frameFinalFlag;
|
||||||
private int frameRsv;
|
private int frameRsv;
|
||||||
private int frameOpcode;
|
private int frameOpcode;
|
||||||
@ -101,7 +101,7 @@ public class WebSocket08FrameDecoder extends ReplayingDecoder<WebSocket08FrameDe
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor with default values
|
* Constructor with default values
|
||||||
*
|
*
|
||||||
* @param maskedPayload
|
* @param maskedPayload
|
||||||
* Web socket servers must set this to true processed incoming masked payload. Client implementations
|
* Web socket servers must set this to true processed incoming masked payload. Client implementations
|
||||||
* must set this to false.
|
* must set this to false.
|
||||||
@ -111,10 +111,10 @@ public class WebSocket08FrameDecoder extends ReplayingDecoder<WebSocket08FrameDe
|
|||||||
public WebSocket08FrameDecoder(boolean maskedPayload, boolean allowExtensions) {
|
public WebSocket08FrameDecoder(boolean maskedPayload, boolean allowExtensions) {
|
||||||
this(maskedPayload, allowExtensions, Long.MAX_VALUE);
|
this(maskedPayload, allowExtensions, Long.MAX_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
* @param maskedPayload
|
* @param maskedPayload
|
||||||
* Web socket servers must set this to true processed incoming masked payload. Client implementations
|
* Web socket servers must set this to true processed incoming masked payload. Client implementations
|
||||||
* must set this to false.
|
* must set this to false.
|
||||||
@ -238,8 +238,8 @@ public class WebSocket08FrameDecoder extends ReplayingDecoder<WebSocket08FrameDe
|
|||||||
framePayloadLength = framePayloadLen1;
|
framePayloadLength = framePayloadLen1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (framePayloadLength > this.maxFramePayloadLength) {
|
if (framePayloadLength > maxFramePayloadLength) {
|
||||||
protocolViolation(channel, "Max frame length of " + this.maxFramePayloadLength + " has been exceeded.");
|
protocolViolation(channel, "Max frame length of " + maxFramePayloadLength + " has been exceeded.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
@ -388,7 +388,7 @@ public class WebSocket08FrameDecoder extends ReplayingDecoder<WebSocket08FrameDe
|
|||||||
throw new CorruptedFrameException(reason);
|
throw new CorruptedFrameException(reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int toFrameLength(long l) throws TooLongFrameException {
|
private static int toFrameLength(long l) throws TooLongFrameException {
|
||||||
if (l > Integer.MAX_VALUE) {
|
if (l > Integer.MAX_VALUE) {
|
||||||
throw new TooLongFrameException("Length:" + l);
|
throw new TooLongFrameException("Length:" + l);
|
||||||
} else {
|
} else {
|
||||||
@ -414,7 +414,7 @@ public class WebSocket08FrameDecoder extends ReplayingDecoder<WebSocket08FrameDe
|
|||||||
protocolViolation(channel, "invalid UTF-8 bytes");
|
protocolViolation(channel, "invalid UTF-8 bytes");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void checkCloseFrameBody(Channel channel, ChannelBuffer buffer) throws CorruptedFrameException {
|
protected void checkCloseFrameBody(Channel channel, ChannelBuffer buffer) throws CorruptedFrameException {
|
||||||
if (buffer == null || buffer.capacity() == 0) {
|
if (buffer == null || buffer.capacity() == 0) {
|
||||||
return;
|
return;
|
||||||
@ -429,8 +429,8 @@ public class WebSocket08FrameDecoder extends ReplayingDecoder<WebSocket08FrameDe
|
|||||||
|
|
||||||
// Must have 2 byte integer within the valid range
|
// Must have 2 byte integer within the valid range
|
||||||
int statusCode = buffer.readShort();
|
int statusCode = buffer.readShort();
|
||||||
if ((statusCode >= 0 && statusCode <= 999) || (statusCode >= 1004 && statusCode <= 1006)
|
if (statusCode >= 0 && statusCode <= 999 || statusCode >= 1004 && statusCode <= 1006
|
||||||
|| (statusCode >= 1012 && statusCode <= 2999)) {
|
|| statusCode >= 1012 && statusCode <= 2999) {
|
||||||
protocolViolation(channel, "Invalid close frame status code: " + statusCode);
|
protocolViolation(channel, "Invalid close frame status code: " + statusCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -444,8 +444,8 @@ public class WebSocket08FrameDecoder extends ReplayingDecoder<WebSocket08FrameDe
|
|||||||
protocolViolation(channel, "Invalid close frame reason text. Invalid UTF-8 bytes");
|
protocolViolation(channel, "Invalid close frame reason text. Invalid UTF-8 bytes");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore reader index
|
// Restore reader index
|
||||||
buffer.readerIndex(idx);
|
buffer.readerIndex(idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor with default values
|
* Constructor with default values
|
||||||
*
|
*
|
||||||
* @param webSocketURL
|
* @param webSocketURL
|
||||||
* URL for web socket communications. e.g "ws://myhost.com/mypath". Subsequent web socket frames will be
|
* URL for web socket communications. e.g "ws://myhost.com/mypath". Subsequent web socket frames will be
|
||||||
* sent to this URL.
|
* sent to this URL.
|
||||||
@ -65,10 +65,10 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker {
|
|||||||
Map<String, String> customHeaders) {
|
Map<String, String> customHeaders) {
|
||||||
this(webSocketURL, version, subprotocol, customHeaders, Long.MAX_VALUE);
|
this(webSocketURL, version, subprotocol, customHeaders, Long.MAX_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
* @param webSocketURL
|
* @param webSocketURL
|
||||||
* URL for web socket communications. e.g "ws://myhost.com/mypath". Subsequent web socket frames will be
|
* URL for web socket communications. e.g "ws://myhost.com/mypath". Subsequent web socket frames will be
|
||||||
* sent to this URL.
|
* sent to this URL.
|
||||||
@ -91,7 +91,7 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker {
|
|||||||
* <p>
|
* <p>
|
||||||
* Sends the opening request to the server:
|
* Sends the opening request to the server:
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* GET /demo HTTP/1.1
|
* GET /demo HTTP/1.1
|
||||||
* Upgrade: WebSocket
|
* Upgrade: WebSocket
|
||||||
@ -100,10 +100,10 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker {
|
|||||||
* Origin: http://example.com
|
* Origin: http://example.com
|
||||||
* Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5
|
* Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5
|
||||||
* Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
|
* Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
|
||||||
*
|
*
|
||||||
* ^n:ds[4U
|
* ^n:ds[4U
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param channel
|
* @param channel
|
||||||
* Channel into which we can write our request
|
* Channel into which we can write our request
|
||||||
*/
|
*/
|
||||||
@ -167,10 +167,10 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker {
|
|||||||
originValue = originValue + ":" + wsPort;
|
originValue = originValue + ":" + wsPort;
|
||||||
}
|
}
|
||||||
request.addHeader(Names.ORIGIN, originValue);
|
request.addHeader(Names.ORIGIN, originValue);
|
||||||
|
|
||||||
request.addHeader(Names.SEC_WEBSOCKET_KEY1, key1);
|
request.addHeader(Names.SEC_WEBSOCKET_KEY1, key1);
|
||||||
request.addHeader(Names.SEC_WEBSOCKET_KEY2, key2);
|
request.addHeader(Names.SEC_WEBSOCKET_KEY2, key2);
|
||||||
String expectedSubprotocol = this.getExpectedSubprotocol();
|
String expectedSubprotocol = getExpectedSubprotocol();
|
||||||
if (expectedSubprotocol != null && !expectedSubprotocol.equals("")) {
|
if (expectedSubprotocol != null && !expectedSubprotocol.equals("")) {
|
||||||
request.addHeader(Names.SEC_WEBSOCKET_PROTOCOL, expectedSubprotocol);
|
request.addHeader(Names.SEC_WEBSOCKET_PROTOCOL, expectedSubprotocol);
|
||||||
}
|
}
|
||||||
@ -194,7 +194,7 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker {
|
|||||||
* <p>
|
* <p>
|
||||||
* Process server response:
|
* Process server response:
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* HTTP/1.1 101 WebSocket Protocol Handshake
|
* HTTP/1.1 101 WebSocket Protocol Handshake
|
||||||
* Upgrade: WebSocket
|
* Upgrade: WebSocket
|
||||||
@ -202,10 +202,10 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker {
|
|||||||
* Sec-WebSocket-Origin: http://example.com
|
* Sec-WebSocket-Origin: http://example.com
|
||||||
* Sec-WebSocket-Location: ws://example.com/demo
|
* Sec-WebSocket-Location: ws://example.com/demo
|
||||||
* Sec-WebSocket-Protocol: sample
|
* Sec-WebSocket-Protocol: sample
|
||||||
*
|
*
|
||||||
* 8jKS'y:G*Co,Wxa-
|
* 8jKS'y:G*Co,Wxa-
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param channel
|
* @param channel
|
||||||
* Channel
|
* Channel
|
||||||
* @param response
|
* @param response
|
||||||
@ -241,12 +241,12 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker {
|
|||||||
setActualSubprotocol(subprotocol);
|
setActualSubprotocol(subprotocol);
|
||||||
|
|
||||||
channel.getPipeline().replace(HttpResponseDecoder.class, "ws-decoder",
|
channel.getPipeline().replace(HttpResponseDecoder.class, "ws-decoder",
|
||||||
new WebSocket00FrameDecoder(this.getMaxFramePayloadLength()));
|
new WebSocket00FrameDecoder(getMaxFramePayloadLength()));
|
||||||
|
|
||||||
setHandshakeComplete();
|
setHandshakeComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String insertRandomCharacters(String key) {
|
private static String insertRandomCharacters(String key) {
|
||||||
int count = WebSocketUtil.randomNumber(1, 12);
|
int count = WebSocketUtil.randomNumber(1, 12);
|
||||||
|
|
||||||
char[] randomChars = new char[count];
|
char[] randomChars = new char[count];
|
||||||
@ -269,7 +269,7 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker {
|
|||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String insertSpaces(String key, int spaces) {
|
private static String insertSpaces(String key, int spaces) {
|
||||||
for (int i = 0; i < spaces; i++) {
|
for (int i = 0; i < spaces; i++) {
|
||||||
int split = WebSocketUtil.randomNumber(1, key.length() - 1);
|
int split = WebSocketUtil.randomNumber(1, key.length() - 1);
|
||||||
String part1 = key.substring(0, split);
|
String part1 = key.substring(0, split);
|
||||||
|
@ -90,37 +90,37 @@ final class SpdyCodecUtil {
|
|||||||
* Reads a big-endian unsigned short integer from the buffer.
|
* Reads a big-endian unsigned short integer from the buffer.
|
||||||
*/
|
*/
|
||||||
static int getUnsignedShort(ChannelBuffer buf, int offset) {
|
static int getUnsignedShort(ChannelBuffer buf, int offset) {
|
||||||
return (int) ((buf.getByte(offset) & 0xFF) << 8 |
|
return (buf.getByte(offset) & 0xFF) << 8 |
|
||||||
(buf.getByte(offset + 1) & 0xFF));
|
buf.getByte(offset + 1) & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a big-endian unsigned medium integer from the buffer.
|
* Reads a big-endian unsigned medium integer from the buffer.
|
||||||
*/
|
*/
|
||||||
static int getUnsignedMedium(ChannelBuffer buf, int offset) {
|
static int getUnsignedMedium(ChannelBuffer buf, int offset) {
|
||||||
return (int) ((buf.getByte(offset) & 0xFF) << 16 |
|
return (buf.getByte(offset) & 0xFF) << 16 |
|
||||||
(buf.getByte(offset + 1) & 0xFF) << 8 |
|
(buf.getByte(offset + 1) & 0xFF) << 8 |
|
||||||
(buf.getByte(offset + 2) & 0xFF));
|
buf.getByte(offset + 2) & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a big-endian (31-bit) integer from the buffer.
|
* Reads a big-endian (31-bit) integer from the buffer.
|
||||||
*/
|
*/
|
||||||
static int getUnsignedInt(ChannelBuffer buf, int offset) {
|
static int getUnsignedInt(ChannelBuffer buf, int offset) {
|
||||||
return (int) ((buf.getByte(offset) & 0x7F) << 24 |
|
return (buf.getByte(offset) & 0x7F) << 24 |
|
||||||
(buf.getByte(offset + 1) & 0xFF) << 16 |
|
(buf.getByte(offset + 1) & 0xFF) << 16 |
|
||||||
(buf.getByte(offset + 2) & 0xFF) << 8 |
|
(buf.getByte(offset + 2) & 0xFF) << 8 |
|
||||||
(buf.getByte(offset + 3) & 0xFF));
|
buf.getByte(offset + 3) & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a big-endian signed integer from the buffer.
|
* Reads a big-endian signed integer from the buffer.
|
||||||
*/
|
*/
|
||||||
static int getSignedInt(ChannelBuffer buf, int offset) {
|
static int getSignedInt(ChannelBuffer buf, int offset) {
|
||||||
return (int) ((buf.getByte(offset) & 0xFF) << 24 |
|
return (buf.getByte(offset) & 0xFF) << 24 |
|
||||||
(buf.getByte(offset + 1) & 0xFF) << 16 |
|
(buf.getByte(offset + 1) & 0xFF) << 16 |
|
||||||
(buf.getByte(offset + 2) & 0xFF) << 8 |
|
(buf.getByte(offset + 2) & 0xFF) << 8 |
|
||||||
(buf.getByte(offset + 3) & 0xFF));
|
buf.getByte(offset + 3) & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,9 +45,20 @@ public class SpdyFrameCodec implements ChannelUpstreamHandler,
|
|||||||
* Creates a new instance with the specified decoder and encoder options.
|
* Creates a new instance with the specified decoder and encoder options.
|
||||||
*/
|
*/
|
||||||
public SpdyFrameCodec(
|
public SpdyFrameCodec(
|
||||||
int maxChunkSize, int maxFrameSize, int maxHeaderSize,
|
int maxChunkSize, int maxHeaderSize,
|
||||||
int compressionLevel, int windowBits, int memLevel) {
|
int compressionLevel, int windowBits, int memLevel) {
|
||||||
decoder = new SpdyFrameDecoder(maxChunkSize, maxFrameSize, maxHeaderSize);
|
decoder = new SpdyFrameDecoder(maxChunkSize, maxHeaderSize);
|
||||||
|
encoder = new SpdyFrameEncoder(compressionLevel, windowBits, memLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance with the specified decoder and encoder options.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public SpdyFrameCodec(
|
||||||
|
int maxChunkSize, @SuppressWarnings("unused") int maxFrameSize, int maxHeaderSize,
|
||||||
|
int compressionLevel, int windowBits, int memLevel) {
|
||||||
|
decoder = new SpdyFrameDecoder(maxChunkSize, maxHeaderSize);
|
||||||
encoder = new SpdyFrameEncoder(compressionLevel, windowBits, memLevel);
|
encoder = new SpdyFrameEncoder(compressionLevel, windowBits, memLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.jboss.netty.handler.codec.spdy;
|
package org.jboss.netty.handler.codec.spdy;
|
||||||
|
|
||||||
|
import static org.jboss.netty.handler.codec.spdy.SpdyCodecUtil.*;
|
||||||
|
|
||||||
import org.jboss.netty.buffer.ChannelBuffer;
|
import org.jboss.netty.buffer.ChannelBuffer;
|
||||||
import org.jboss.netty.buffer.ChannelBuffers;
|
import org.jboss.netty.buffer.ChannelBuffers;
|
||||||
import org.jboss.netty.channel.Channel;
|
import org.jboss.netty.channel.Channel;
|
||||||
@ -23,8 +25,6 @@ import org.jboss.netty.channel.Channels;
|
|||||||
import org.jboss.netty.handler.codec.frame.FrameDecoder;
|
import org.jboss.netty.handler.codec.frame.FrameDecoder;
|
||||||
import org.jboss.netty.handler.codec.frame.TooLongFrameException;
|
import org.jboss.netty.handler.codec.frame.TooLongFrameException;
|
||||||
|
|
||||||
import static org.jboss.netty.handler.codec.spdy.SpdyCodecUtil.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decodes {@link ChannelBuffer}s into SPDY Data and Control Frames.
|
* Decodes {@link ChannelBuffer}s into SPDY Data and Control Frames.
|
||||||
*/
|
*/
|
||||||
@ -76,7 +76,7 @@ public class SpdyFrameDecoder extends FrameDecoder {
|
|||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public SpdyFrameDecoder(
|
public SpdyFrameDecoder(
|
||||||
int maxChunkSize, int maxFrameSize, int maxHeaderSize) {
|
int maxChunkSize, @SuppressWarnings("unused") int maxFrameSize, int maxHeaderSize) {
|
||||||
this(maxChunkSize, maxHeaderSize);
|
this(maxChunkSize, maxHeaderSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ public class SpdyFrameDecoder extends FrameDecoder {
|
|||||||
}
|
}
|
||||||
this.maxChunkSize = maxChunkSize;
|
this.maxChunkSize = maxChunkSize;
|
||||||
this.maxHeaderSize = maxHeaderSize;
|
this.maxHeaderSize = maxHeaderSize;
|
||||||
this.state = State.READ_COMMON_HEADER;
|
state = State.READ_COMMON_HEADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -166,7 +166,7 @@ public class SpdyFrameDecoder extends FrameDecoder {
|
|||||||
// Chromium Issue 79156
|
// Chromium Issue 79156
|
||||||
// SPDY setting ids are not written in network byte order
|
// SPDY setting ids are not written in network byte order
|
||||||
// Read id assuming the architecture is little endian
|
// Read id assuming the architecture is little endian
|
||||||
int ID = (buffer.readByte() & 0xFF) |
|
int ID = buffer.readByte() & 0xFF |
|
||||||
(buffer.readByte() & 0xFF) << 8 |
|
(buffer.readByte() & 0xFF) << 8 |
|
||||||
(buffer.readByte() & 0xFF) << 16;
|
(buffer.readByte() & 0xFF) << 16;
|
||||||
byte ID_flags = buffer.readByte();
|
byte ID_flags = buffer.readByte();
|
||||||
@ -181,7 +181,7 @@ public class SpdyFrameDecoder extends FrameDecoder {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(spdySettingsFrame.isSet(ID))) {
|
if (!spdySettingsFrame.isSet(ID)) {
|
||||||
boolean persistVal = (ID_flags & SPDY_SETTINGS_PERSIST_VALUE) != 0;
|
boolean persistVal = (ID_flags & SPDY_SETTINGS_PERSIST_VALUE) != 0;
|
||||||
boolean persisted = (ID_flags & SPDY_SETTINGS_PERSISTED) != 0;
|
boolean persisted = (ID_flags & SPDY_SETTINGS_PERSISTED) != 0;
|
||||||
spdySettingsFrame.setValue(ID, value, persistVal, persisted);
|
spdySettingsFrame.setValue(ID, value, persistVal, persisted);
|
||||||
@ -438,7 +438,7 @@ public class SpdyFrameDecoder extends FrameDecoder {
|
|||||||
|
|
||||||
case SPDY_HEADERS_FRAME:
|
case SPDY_HEADERS_FRAME:
|
||||||
// Protocol allows length 4 frame when there are no name/value pairs
|
// Protocol allows length 4 frame when there are no name/value pairs
|
||||||
int minLength = (length == 4) ? 4 : 8;
|
int minLength = length == 4 ? 4 : 8;
|
||||||
if (buffer.readableBytes() < minLength) {
|
if (buffer.readableBytes() < minLength) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -695,7 +695,7 @@ public class SpdyFrameDecoder extends FrameDecoder {
|
|||||||
fireProtocolException(ctx, message);
|
fireProtocolException(ctx, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fireProtocolException(ChannelHandlerContext ctx, String message) {
|
private static void fireProtocolException(ChannelHandlerContext ctx, String message) {
|
||||||
Channels.fireExceptionCaught(ctx, new SpdyProtocolException(message));
|
Channels.fireExceptionCaught(ctx, new SpdyProtocolException(message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.jboss.netty.handler.codec.spdy;
|
package org.jboss.netty.handler.codec.spdy;
|
||||||
|
|
||||||
|
import static org.jboss.netty.handler.codec.spdy.SpdyCodecUtil.*;
|
||||||
|
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -26,8 +28,6 @@ import org.jboss.netty.channel.ChannelHandlerContext;
|
|||||||
import org.jboss.netty.channel.ChannelStateEvent;
|
import org.jboss.netty.channel.ChannelStateEvent;
|
||||||
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
|
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
|
||||||
|
|
||||||
import static org.jboss.netty.handler.codec.spdy.SpdyCodecUtil.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes a SPDY Data or Control Frame into a {@link ChannelBuffer}.
|
* Encodes a SPDY Data or Control Frame into a {@link ChannelBuffer}.
|
||||||
*/
|
*/
|
||||||
@ -99,7 +99,7 @@ public class SpdyFrameEncoder extends OneToOneEncoder {
|
|||||||
flags |= SPDY_FLAG_UNIDIRECTIONAL;
|
flags |= SPDY_FLAG_UNIDIRECTIONAL;
|
||||||
}
|
}
|
||||||
int headerBlockLength = data.readableBytes();
|
int headerBlockLength = data.readableBytes();
|
||||||
int length = (headerBlockLength == 0) ? 12 : 10 + headerBlockLength;
|
int length = headerBlockLength == 0 ? 12 : 10 + headerBlockLength;
|
||||||
ChannelBuffer frame = ChannelBuffers.buffer(
|
ChannelBuffer frame = ChannelBuffers.buffer(
|
||||||
ByteOrder.BIG_ENDIAN, SPDY_HEADER_SIZE + length);
|
ByteOrder.BIG_ENDIAN, SPDY_HEADER_SIZE + length);
|
||||||
frame.writeShort(SPDY_VERSION | 0x8000);
|
frame.writeShort(SPDY_VERSION | 0x8000);
|
||||||
@ -108,7 +108,7 @@ public class SpdyFrameEncoder extends OneToOneEncoder {
|
|||||||
frame.writeMedium(length);
|
frame.writeMedium(length);
|
||||||
frame.writeInt(spdySynStreamFrame.getStreamID());
|
frame.writeInt(spdySynStreamFrame.getStreamID());
|
||||||
frame.writeInt(spdySynStreamFrame.getAssociatedToStreamID());
|
frame.writeInt(spdySynStreamFrame.getAssociatedToStreamID());
|
||||||
frame.writeShort(((short) spdySynStreamFrame.getPriority()) << 14);
|
frame.writeShort((spdySynStreamFrame.getPriority() & 0xFF) << 14);
|
||||||
if (data.readableBytes() == 0) {
|
if (data.readableBytes() == 0) {
|
||||||
frame.writeShort(0);
|
frame.writeShort(0);
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ public class SpdyFrameEncoder extends OneToOneEncoder {
|
|||||||
encodeHeaderBlock(spdySynReplyFrame));
|
encodeHeaderBlock(spdySynReplyFrame));
|
||||||
byte flags = spdySynReplyFrame.isLast() ? SPDY_FLAG_FIN : 0;
|
byte flags = spdySynReplyFrame.isLast() ? SPDY_FLAG_FIN : 0;
|
||||||
int headerBlockLength = data.readableBytes();
|
int headerBlockLength = data.readableBytes();
|
||||||
int length = (headerBlockLength == 0) ? 8 : 6 + headerBlockLength;
|
int length = headerBlockLength == 0 ? 8 : 6 + headerBlockLength;
|
||||||
ChannelBuffer frame = ChannelBuffers.buffer(
|
ChannelBuffer frame = ChannelBuffers.buffer(
|
||||||
ByteOrder.BIG_ENDIAN, SPDY_HEADER_SIZE + length);
|
ByteOrder.BIG_ENDIAN, SPDY_HEADER_SIZE + length);
|
||||||
frame.writeShort(SPDY_VERSION | 0x8000);
|
frame.writeShort(SPDY_VERSION | 0x8000);
|
||||||
@ -175,9 +175,9 @@ public class SpdyFrameEncoder extends OneToOneEncoder {
|
|||||||
// Chromium Issue 79156
|
// Chromium Issue 79156
|
||||||
// SPDY setting ids are not written in network byte order
|
// SPDY setting ids are not written in network byte order
|
||||||
// Write id assuming the architecture is little endian
|
// Write id assuming the architecture is little endian
|
||||||
frame.writeByte((id >> 0) & 0xFF);
|
frame.writeByte(id >> 0 & 0xFF);
|
||||||
frame.writeByte((id >> 8) & 0xFF);
|
frame.writeByte(id >> 8 & 0xFF);
|
||||||
frame.writeByte((id >> 16) & 0xFF);
|
frame.writeByte(id >> 16 & 0xFF);
|
||||||
frame.writeByte(ID_flags);
|
frame.writeByte(ID_flags);
|
||||||
frame.writeInt(spdySettingsFrame.getValue(id));
|
frame.writeInt(spdySettingsFrame.getValue(id));
|
||||||
}
|
}
|
||||||
@ -220,7 +220,7 @@ public class SpdyFrameEncoder extends OneToOneEncoder {
|
|||||||
ChannelBuffer data = compressHeaderBlock(
|
ChannelBuffer data = compressHeaderBlock(
|
||||||
encodeHeaderBlock(spdyHeadersFrame));
|
encodeHeaderBlock(spdyHeadersFrame));
|
||||||
int headerBlockLength = data.readableBytes();
|
int headerBlockLength = data.readableBytes();
|
||||||
int length = (headerBlockLength == 0) ? 4 : 6 + headerBlockLength;
|
int length = headerBlockLength == 0 ? 4 : 6 + headerBlockLength;
|
||||||
ChannelBuffer frame = ChannelBuffers.buffer(
|
ChannelBuffer frame = ChannelBuffers.buffer(
|
||||||
ByteOrder.BIG_ENDIAN, SPDY_HEADER_SIZE + length);
|
ByteOrder.BIG_ENDIAN, SPDY_HEADER_SIZE + length);
|
||||||
frame.writeShort(SPDY_VERSION | 0x8000);
|
frame.writeShort(SPDY_VERSION | 0x8000);
|
||||||
@ -237,7 +237,7 @@ public class SpdyFrameEncoder extends OneToOneEncoder {
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChannelBuffer encodeHeaderBlock(SpdyHeaderBlock headerFrame)
|
private static ChannelBuffer encodeHeaderBlock(SpdyHeaderBlock headerFrame)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
Set<String> names = headerFrame.getHeaderNames();
|
Set<String> names = headerFrame.getHeaderNames();
|
||||||
int numHeaders = names.size();
|
int numHeaders = names.size();
|
||||||
|
@ -220,7 +220,7 @@ public class SpdyHttpDecoder extends OneToOneDecoder {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpRequest createHttpRequest(SpdyHeaderBlock requestFrame)
|
private static HttpRequest createHttpRequest(SpdyHeaderBlock requestFrame)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
// Create the first line of the request from the name/value pairs
|
// Create the first line of the request from the name/value pairs
|
||||||
HttpMethod method = SpdyHeaders.getMethod(requestFrame);
|
HttpMethod method = SpdyHeaders.getMethod(requestFrame);
|
||||||
@ -250,7 +250,7 @@ public class SpdyHttpDecoder extends OneToOneDecoder {
|
|||||||
return httpRequest;
|
return httpRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpResponse createHttpResponse(SpdyHeaderBlock responseFrame)
|
private static HttpResponse createHttpResponse(SpdyHeaderBlock responseFrame)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
// Create the first line of the response from the name/value pairs
|
// Create the first line of the response from the name/value pairs
|
||||||
HttpResponseStatus status = SpdyHeaders.getStatus(responseFrame);
|
HttpResponseStatus status = SpdyHeaders.getStatus(responseFrame);
|
||||||
|
@ -19,4 +19,5 @@ package org.jboss.netty.handler.codec.spdy;
|
|||||||
* A SPDY Protocol NOOP Control Frame
|
* A SPDY Protocol NOOP Control Frame
|
||||||
*/
|
*/
|
||||||
public interface SpdyNoOpFrame {
|
public interface SpdyNoOpFrame {
|
||||||
|
// Tag interface
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
|||||||
/**
|
/**
|
||||||
* Manages streams within a SPDY session.
|
* Manages streams within a SPDY session.
|
||||||
*/
|
*/
|
||||||
public class SpdySessionHandler extends SimpleChannelUpstreamHandler
|
public class SpdySessionHandler extends SimpleChannelUpstreamHandler
|
||||||
implements ChannelDownstreamHandler {
|
implements ChannelDownstreamHandler {
|
||||||
|
|
||||||
private static final SpdyProtocolException PROTOCOL_EXCEPTION = new SpdyProtocolException();
|
private static final SpdyProtocolException PROTOCOL_EXCEPTION = new SpdyProtocolException();
|
||||||
@ -218,12 +218,12 @@ public class SpdySessionHandler extends SimpleChannelUpstreamHandler
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
SpdyPingFrame spdyPingFrame = (SpdyPingFrame) msg;
|
SpdyPingFrame spdyPingFrame = (SpdyPingFrame) msg;
|
||||||
|
|
||||||
if (isRemoteInitiatedID(spdyPingFrame.getID())) {
|
if (isRemoteInitiatedID(spdyPingFrame.getID())) {
|
||||||
Channels.write(ctx, Channels.future(e.getChannel()), spdyPingFrame, e.getRemoteAddress());
|
Channels.write(ctx, Channels.future(e.getChannel()), spdyPingFrame, e.getRemoteAddress());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: only checks that there are outstanding pings since uniqueness is not inforced
|
// Note: only checks that there are outstanding pings since uniqueness is not inforced
|
||||||
if (pings.get() == 0) {
|
if (pings.get() == 0) {
|
||||||
return;
|
return;
|
||||||
@ -393,7 +393,7 @@ public class SpdySessionHandler extends SimpleChannelUpstreamHandler
|
|||||||
|
|
||||||
private boolean isRemoteInitiatedID(int ID) {
|
private boolean isRemoteInitiatedID(int ID) {
|
||||||
boolean serverID = SpdyCodecUtil.isServerID(ID);
|
boolean serverID = SpdyCodecUtil.isServerID(ID);
|
||||||
return (server && !serverID) || (!server && serverID);
|
return server && !serverID || !server && serverID;
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void updateConcurrentStreams(SpdySettingsFrame settings, boolean remote) {
|
private synchronized void updateConcurrentStreams(SpdySettingsFrame settings, boolean remote) {
|
||||||
@ -429,8 +429,8 @@ public class SpdySessionHandler extends SimpleChannelUpstreamHandler
|
|||||||
if (receivedGoAwayFrame || sentGoAwayFrame) {
|
if (receivedGoAwayFrame || sentGoAwayFrame) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ((maxConcurrentStreams != 0) &&
|
if (maxConcurrentStreams != 0 &&
|
||||||
(spdySession.numActiveStreams() >= maxConcurrentStreams)) {
|
spdySession.numActiveStreams() >= maxConcurrentStreams) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
spdySession.acceptStream(streamID, remoteSideClosed, localSideClosed);
|
spdySession.acceptStream(streamID, remoteSideClosed, localSideClosed);
|
||||||
@ -446,14 +446,14 @@ public class SpdySessionHandler extends SimpleChannelUpstreamHandler
|
|||||||
} else {
|
} else {
|
||||||
spdySession.closeLocalSide(streamID);
|
spdySession.closeLocalSide(streamID);
|
||||||
}
|
}
|
||||||
if ((closeSessionFuture != null) && spdySession.noActiveStreams()) {
|
if (closeSessionFuture != null && spdySession.noActiveStreams()) {
|
||||||
closeSessionFuture.setSuccess();
|
closeSessionFuture.setSuccess();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeStream(int streamID) {
|
private void removeStream(int streamID) {
|
||||||
spdySession.removeStream(streamID);
|
spdySession.removeStream(streamID);
|
||||||
if ((closeSessionFuture != null) && spdySession.noActiveStreams()) {
|
if (closeSessionFuture != null && spdySession.noActiveStreams()) {
|
||||||
closeSessionFuture.setSuccess();
|
closeSessionFuture.setSuccess();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -479,7 +479,7 @@ public class SpdySessionHandler extends SimpleChannelUpstreamHandler
|
|||||||
if (!sentGoAwayFrame) {
|
if (!sentGoAwayFrame) {
|
||||||
sentGoAwayFrame = true;
|
sentGoAwayFrame = true;
|
||||||
ChannelFuture future = Channels.future(channel);
|
ChannelFuture future = Channels.future(channel);
|
||||||
Channels.write(ctx, future, new DefaultSpdyGoAwayFrame(lastGoodStreamID));
|
Channels.write(ctx, future, new DefaultSpdyGoAwayFrame(lastGoodStreamID), remoteAddress);
|
||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
return Channels.succeededFuture(channel);
|
return Channels.succeededFuture(channel);
|
||||||
|
@ -33,6 +33,7 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||||||
import org.jboss.netty.buffer.ChannelBuffer;
|
import org.jboss.netty.buffer.ChannelBuffer;
|
||||||
import org.jboss.netty.channel.Channel;
|
import org.jboss.netty.channel.Channel;
|
||||||
import org.jboss.netty.channel.ChannelEvent;
|
import org.jboss.netty.channel.ChannelEvent;
|
||||||
|
import org.jboss.netty.channel.ChannelFuture;
|
||||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||||
import org.jboss.netty.channel.ChannelState;
|
import org.jboss.netty.channel.ChannelState;
|
||||||
import org.jboss.netty.channel.ChannelStateEvent;
|
import org.jboss.netty.channel.ChannelStateEvent;
|
||||||
@ -260,7 +261,7 @@ public class MemoryAwareThreadPoolExecutor extends ThreadPoolExecutor {
|
|||||||
// Misuse check
|
// Misuse check
|
||||||
misuseDetector.increase();
|
misuseDetector.increase();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void terminated() {
|
protected void terminated() {
|
||||||
super.terminated();
|
super.terminated();
|
||||||
@ -274,16 +275,16 @@ public class MemoryAwareThreadPoolExecutor extends ThreadPoolExecutor {
|
|||||||
public List<Runnable> shutdownNow() {
|
public List<Runnable> shutdownNow() {
|
||||||
return shutdownNow(notifyOnShutdown);
|
return shutdownNow(notifyOnShutdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See {@link ThreadPoolExecutor#shutdownNow()} for how it handles the shutdown. If <code>true</code> is given to this method it also notifies all {@link ChannelFuture}'s
|
* See {@link ThreadPoolExecutor#shutdownNow()} for how it handles the shutdown. If <code>true</code> is given to this method it also notifies all {@link ChannelFuture}'s
|
||||||
* of the not executed {@link ChannelEventRunnable}'s.
|
* of the not executed {@link ChannelEventRunnable}'s.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Be aware that if you call this with <code>false</code> you will need to handle the notification of the {@link ChannelFuture}'s by your self. So only use this if you
|
* Be aware that if you call this with <code>false</code> you will need to handle the notification of the {@link ChannelFuture}'s by your self. So only use this if you
|
||||||
* really have a use-case for it.
|
* really have a use-case for it.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public List<Runnable> shutdownNow(boolean notify) {
|
public List<Runnable> shutdownNow(boolean notify) {
|
||||||
if (!notify) {
|
if (!notify) {
|
||||||
@ -302,17 +303,17 @@ public class MemoryAwareThreadPoolExecutor extends ThreadPoolExecutor {
|
|||||||
}
|
}
|
||||||
ChannelEvent event = ((ChannelEventRunnable) task).getEvent();
|
ChannelEvent event = ((ChannelEventRunnable) task).getEvent();
|
||||||
event.getFuture().setFailure(cause);
|
event.getFuture().setFailure(cause);
|
||||||
|
|
||||||
if (channels == null) {
|
if (channels == null) {
|
||||||
channels = new HashSet<Channel>();
|
channels = new HashSet<Channel>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// store the Channel of the event for later notification of the exceptionCaught event
|
// store the Channel of the event for later notification of the exceptionCaught event
|
||||||
channels.add(event.getChannel());
|
channels.add(event.getChannel());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop over all channels and fire an exceptionCaught event
|
// loop over all channels and fire an exceptionCaught event
|
||||||
if (channels != null) {
|
if (channels != null) {
|
||||||
for (Channel channel: channels) {
|
for (Channel channel: channels) {
|
||||||
@ -376,7 +377,7 @@ public class MemoryAwareThreadPoolExecutor extends ThreadPoolExecutor {
|
|||||||
return totalLimiter.limit;
|
return totalLimiter.limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated <tt>maxTotalMemorySize</tt> is not modifiable anymore.
|
* @deprecated <tt>maxTotalMemorySize</tt> is not modifiable anymore.
|
||||||
*/
|
*/
|
||||||
@ -396,7 +397,7 @@ public class MemoryAwareThreadPoolExecutor extends ThreadPoolExecutor {
|
|||||||
/**
|
/**
|
||||||
* If set to <code>false</code> no queued {@link ChannelEventRunnable}'s {@link ChannelFuture} will get notified once {@link #shutdownNow()} is called.
|
* If set to <code>false</code> no queued {@link ChannelEventRunnable}'s {@link ChannelFuture} will get notified once {@link #shutdownNow()} is called.
|
||||||
* If set to <code>true</code> every queued {@link ChannelEventRunnable} will get marked as failed via {@link ChannelFuture#setFailure(Throwable)}.
|
* If set to <code>true</code> every queued {@link ChannelEventRunnable} will get marked as failed via {@link ChannelFuture#setFailure(Throwable)}.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Please only set this to <code>false</code> if you want to handle the notification by yourself and know what you are doing. Default is <code>true</code>.
|
* Please only set this to <code>false</code> if you want to handle the notification by yourself and know what you are doing. Default is <code>true</code>.
|
||||||
* </p>
|
* </p>
|
||||||
@ -404,17 +405,17 @@ public class MemoryAwareThreadPoolExecutor extends ThreadPoolExecutor {
|
|||||||
public void setNotifyChannelFuturesOnShutdown(boolean notifyOnShutdown) {
|
public void setNotifyChannelFuturesOnShutdown(boolean notifyOnShutdown) {
|
||||||
this.notifyOnShutdown = notifyOnShutdown;
|
this.notifyOnShutdown = notifyOnShutdown;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns if the {@link ChannelFuture}'s of the {@link ChannelEventRunnable}'s should be notified about the shutdown of this {@link MemoryAwareThreadPoolExecutor}.
|
* Returns if the {@link ChannelFuture}'s of the {@link ChannelEventRunnable}'s should be notified about the shutdown of this {@link MemoryAwareThreadPoolExecutor}.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public boolean getNotifyChannelFuturesOnShutdown() {
|
public boolean getNotifyChannelFuturesOnShutdown() {
|
||||||
return notifyOnShutdown;
|
return notifyOnShutdown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(Runnable command) {
|
public void execute(Runnable command) {
|
||||||
if (command instanceof ChannelDownstreamEventRunnable) {
|
if (command instanceof ChannelDownstreamEventRunnable) {
|
||||||
@ -523,7 +524,7 @@ public class MemoryAwareThreadPoolExecutor extends ThreadPoolExecutor {
|
|||||||
//System.out.println("READABLE");
|
//System.out.println("READABLE");
|
||||||
ChannelHandlerContext ctx = eventTask.getContext();
|
ChannelHandlerContext ctx = eventTask.getContext();
|
||||||
if (ctx.getHandler() instanceof ExecutionHandler) {
|
if (ctx.getHandler() instanceof ExecutionHandler) {
|
||||||
// check if the attachment was set as this means that we suspend the channel from reads. This only works when
|
// check if the attachment was set as this means that we suspend the channel from reads. This only works when
|
||||||
// this pool is used with ExecutionHandler but I guess thats good enough for us.
|
// this pool is used with ExecutionHandler but I guess thats good enough for us.
|
||||||
//
|
//
|
||||||
// See #215
|
// See #215
|
||||||
|
@ -239,7 +239,7 @@ public class BlockingReadHandler<E> extends SimpleChannelUpstreamHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void detectDeadLock() {
|
private static void detectDeadLock() {
|
||||||
if (DeadLockProofWorker.PARENT.get() != null) {
|
if (DeadLockProofWorker.PARENT.get() != null) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"read*(...) in I/O thread causes a dead lock or " +
|
"read*(...) in I/O thread causes a dead lock or " +
|
||||||
@ -267,7 +267,6 @@ public class BlockingReadHandler<E> extends SimpleChannelUpstreamHandler {
|
|||||||
getQueue().put(e);
|
getQueue().put(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private E getMessage(MessageEvent e) {
|
private E getMessage(MessageEvent e) {
|
||||||
return (E) e.getMessage();
|
return (E) e.getMessage();
|
||||||
}
|
}
|
||||||
|
@ -67,15 +67,15 @@ import org.jboss.netty.util.internal.QueueFactory;
|
|||||||
* renegotiating. You will be notified by the {@link ChannelFuture} which is
|
* renegotiating. You will be notified by the {@link ChannelFuture} which is
|
||||||
* returned by the {@link #handshake()} method when the handshake
|
* returned by the {@link #handshake()} method when the handshake
|
||||||
* process succeeds or fails.
|
* process succeeds or fails.
|
||||||
*
|
*
|
||||||
* <h3>Handshake</h3>
|
* <h3>Handshake</h3>
|
||||||
* <p>
|
* <p>
|
||||||
* If {@link #isIssueHandshake()} is {@code false}
|
* If {@link #isIssueHandshake()} is {@code false}
|
||||||
* (default) you will need to take care of calling {@link #handshake()} by your own. In most situations were {@link SslHandler} is used in 'client mode'
|
* (default) you will need to take care of calling {@link #handshake()} by your own. In most situations were {@link SslHandler} is used in 'client mode'
|
||||||
* you want to issue a handshake once the connection was established. if {@link #setIssueHandshake(boolean)} is set to <code>true</code> you don't need to
|
* you want to issue a handshake once the connection was established. if {@link #setIssueHandshake(boolean)} is set to <code>true</code> you don't need to
|
||||||
* worry about this as the {@link SslHandler} will take care of it.
|
* worry about this as the {@link SslHandler} will take care of it.
|
||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* <h3>Renegotiation</h3>
|
* <h3>Renegotiation</h3>
|
||||||
* <p>
|
* <p>
|
||||||
* If {@link #isEnableRenegotiation() enableRenegotiation} is {@code true}
|
* If {@link #isEnableRenegotiation() enableRenegotiation} is {@code true}
|
||||||
@ -198,7 +198,7 @@ public class SslHandler extends FrameDecoder
|
|||||||
private final NonReentrantLock pendingEncryptedWritesLock = new NonReentrantLock();
|
private final NonReentrantLock pendingEncryptedWritesLock = new NonReentrantLock();
|
||||||
|
|
||||||
private volatile boolean issueHandshake;
|
private volatile boolean issueHandshake;
|
||||||
|
|
||||||
private static final ChannelFutureListener HANDSHAKE_LISTENER = new ChannelFutureListener() {
|
private static final ChannelFutureListener HANDSHAKE_LISTENER = new ChannelFutureListener() {
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
public void operationComplete(ChannelFuture future) throws Exception {
|
||||||
if (!future.isSuccess()) {
|
if (!future.isSuccess()) {
|
||||||
@ -206,9 +206,9 @@ public class SslHandler extends FrameDecoder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final SSLEngineInboundCloseFuture sslEngineCloseFuture = new SSLEngineInboundCloseFuture();
|
private final SSLEngineInboundCloseFuture sslEngineCloseFuture = new SSLEngineInboundCloseFuture();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance.
|
* Creates a new instance.
|
||||||
*
|
*
|
||||||
@ -386,7 +386,7 @@ public class SslHandler extends FrameDecoder
|
|||||||
* @deprecated Use {@link #handshake()} instead.
|
* @deprecated Use {@link #handshake()} instead.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public ChannelFuture handshake(Channel channel) {
|
public ChannelFuture handshake(@SuppressWarnings("unused") Channel channel) {
|
||||||
return handshake();
|
return handshake();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -410,7 +410,7 @@ public class SslHandler extends FrameDecoder
|
|||||||
* @deprecated Use {@link #close()} instead.
|
* @deprecated Use {@link #close()} instead.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public ChannelFuture close(Channel channel) {
|
public ChannelFuture close(@SuppressWarnings("unused") Channel channel) {
|
||||||
return close();
|
return close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,18 +446,18 @@ public class SslHandler extends FrameDecoder
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the {@link ChannelFuture} that will get notified if the inbound of the {@link SSLEngine} will get closed.
|
* Return the {@link ChannelFuture} that will get notified if the inbound of the {@link SSLEngine} will get closed.
|
||||||
*
|
*
|
||||||
* This method will return the same {@link ChannelFuture} all the time.
|
* This method will return the same {@link ChannelFuture} all the time.
|
||||||
*
|
*
|
||||||
* For more informations see the apidocs of {@link SSLEngine}
|
* For more informations see the apidocs of {@link SSLEngine}
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public ChannelFuture getSSLEngineInboundCloseFuture() {
|
public ChannelFuture getSSLEngineInboundCloseFuture() {
|
||||||
return sslEngineCloseFuture;
|
return sslEngineCloseFuture;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void handleDownstream(
|
public void handleDownstream(
|
||||||
final ChannelHandlerContext context, final ChannelEvent evt) throws Exception {
|
final ChannelHandlerContext context, final ChannelEvent evt) throws Exception {
|
||||||
if (evt instanceof ChannelStateEvent) {
|
if (evt instanceof ChannelStateEvent) {
|
||||||
@ -476,7 +476,7 @@ public class SslHandler extends FrameDecoder
|
|||||||
context.sendDownstream(evt);
|
context.sendDownstream(evt);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageEvent e = (MessageEvent) evt;
|
MessageEvent e = (MessageEvent) evt;
|
||||||
if (!(e.getMessage() instanceof ChannelBuffer)) {
|
if (!(e.getMessage() instanceof ChannelBuffer)) {
|
||||||
context.sendDownstream(evt);
|
context.sendDownstream(evt);
|
||||||
@ -551,7 +551,7 @@ public class SslHandler extends FrameDecoder
|
|||||||
"Swallowing an exception raised while " +
|
"Swallowing an exception raised while " +
|
||||||
"writing non-app data", cause);
|
"writing non-app data", cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -944,7 +944,7 @@ public class SslHandler extends FrameDecoder
|
|||||||
!engine.getUseClientMode() &&
|
!engine.getUseClientMode() &&
|
||||||
!engine.isInboundDone() && !engine.isOutboundDone()) {
|
!engine.isInboundDone() && !engine.isOutboundDone()) {
|
||||||
needsHandshake = true;
|
needsHandshake = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (needsHandshake) {
|
if (needsHandshake) {
|
||||||
@ -954,13 +954,13 @@ public class SslHandler extends FrameDecoder
|
|||||||
synchronized (handshakeLock) {
|
synchronized (handshakeLock) {
|
||||||
result = engine.unwrap(inNetBuf, outAppBuf);
|
result = engine.unwrap(inNetBuf, outAppBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// notify about the CLOSED state of the SSLEngine. See #137
|
// notify about the CLOSED state of the SSLEngine. See #137
|
||||||
if (result.getStatus() == Status.CLOSED) {
|
if (result.getStatus() == Status.CLOSED) {
|
||||||
sslEngineCloseFuture.setClosed();
|
sslEngineCloseFuture.setClosed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
final HandshakeStatus handshakeStatus = result.getHandshakeStatus();
|
final HandshakeStatus handshakeStatus = result.getHandshakeStatus();
|
||||||
handleRenegotiation(handshakeStatus);
|
handleRenegotiation(handshakeStatus);
|
||||||
switch (handshakeStatus) {
|
switch (handshakeStatus) {
|
||||||
@ -987,9 +987,9 @@ public class SslHandler extends FrameDecoder
|
|||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"Unknown handshake status: " + handshakeStatus);
|
"Unknown handshake status: " + handshakeStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needsWrap) {
|
if (needsWrap) {
|
||||||
// wrap() acquires pendingUnencryptedWrites first and then
|
// wrap() acquires pendingUnencryptedWrites first and then
|
||||||
// handshakeLock. If handshakeLock is already hold by the
|
// handshakeLock. If handshakeLock is already hold by the
|
||||||
@ -1123,7 +1123,7 @@ public class SslHandler extends FrameDecoder
|
|||||||
// is managing.
|
// is managing.
|
||||||
|
|
||||||
engine.closeOutbound();
|
engine.closeOutbound();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
engine.closeInbound();
|
engine.closeInbound();
|
||||||
} catch (SSLException e) {
|
} catch (SSLException e) {
|
||||||
@ -1135,7 +1135,7 @@ public class SslHandler extends FrameDecoder
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handshakeFuture.setFailure(cause);
|
handshakeFuture.setFailure(cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1226,7 +1226,7 @@ public class SslHandler extends FrameDecoder
|
|||||||
* Fail all pending writes which we were not able to flush out
|
* Fail all pending writes which we were not able to flush out
|
||||||
*/
|
*/
|
||||||
public void afterRemove(ChannelHandlerContext ctx) throws Exception {
|
public void afterRemove(ChannelHandlerContext ctx) throws Exception {
|
||||||
|
|
||||||
// there is no need for synchronization here as we do not receive downstream events anymore
|
// there is no need for synchronization here as we do not receive downstream events anymore
|
||||||
Throwable cause = null;
|
Throwable cause = null;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -1257,8 +1257,8 @@ public class SslHandler extends FrameDecoder
|
|||||||
fireExceptionCaughtLater(ctx, cause);
|
fireExceptionCaughtLater(ctx, cause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls {@link #handshake()} once the {@link Channel} is connected
|
* Calls {@link #handshake()} once the {@link Channel} is connected
|
||||||
*/
|
*/
|
||||||
@ -1270,10 +1270,10 @@ public class SslHandler extends FrameDecoder
|
|||||||
}
|
}
|
||||||
super.channelConnected(ctx, e);
|
super.channelConnected(ctx, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loop over all the pending writes and fail them.
|
* Loop over all the pending writes and fail them.
|
||||||
*
|
*
|
||||||
* See <a href="https://github.com/netty/netty/issues/305">#305</a> for more details.
|
* See <a href="https://github.com/netty/netty/issues/305">#305</a> for more details.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@ -1289,10 +1289,10 @@ public class SslHandler extends FrameDecoder
|
|||||||
cause = new ClosedChannelException();
|
cause = new ClosedChannelException();
|
||||||
}
|
}
|
||||||
pw.future.setFailure(cause);
|
pw.future.setFailure(cause);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
MessageEvent ev = pendingEncryptedWrites.poll();
|
MessageEvent ev = pendingEncryptedWrites.poll();
|
||||||
if (ev == null) {
|
if (ev == null) {
|
||||||
@ -1302,14 +1302,14 @@ public class SslHandler extends FrameDecoder
|
|||||||
cause = new ClosedChannelException();
|
cause = new ClosedChannelException();
|
||||||
}
|
}
|
||||||
ev.getFuture().setFailure(cause);
|
ev.getFuture().setFailure(cause);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cause != null) {
|
if (cause != null) {
|
||||||
fireExceptionCaught(ctx, cause);
|
fireExceptionCaught(ctx, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
super.channelClosed(ctx, e);
|
super.channelClosed(ctx, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1317,9 +1317,9 @@ public class SslHandler extends FrameDecoder
|
|||||||
public SSLEngineInboundCloseFuture() {
|
public SSLEngineInboundCloseFuture() {
|
||||||
super(null, true);
|
super(null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setClosed() {
|
void setClosed() {
|
||||||
super.setSuccess();
|
super.setSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -307,9 +307,9 @@ public class IdleStateHandler extends SimpleChannelUpstreamHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void destroy(ChannelHandlerContext ctx) {
|
private static void destroy(ChannelHandlerContext ctx) {
|
||||||
State state;
|
State state;
|
||||||
|
|
||||||
synchronized (ctx) {
|
synchronized (ctx) {
|
||||||
state = state(ctx);
|
state = state(ctx);
|
||||||
state.destroyed = true;
|
state.destroyed = true;
|
||||||
@ -328,8 +328,8 @@ public class IdleStateHandler extends SimpleChannelUpstreamHandler
|
|||||||
state.allIdleTimeout = null;
|
state.allIdleTimeout = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private State state(ChannelHandlerContext ctx) {
|
private static State state(ChannelHandlerContext ctx) {
|
||||||
State state;
|
State state;
|
||||||
synchronized (ctx) {
|
synchronized (ctx) {
|
||||||
// FIXME: It could have been better if there is setAttachmentIfAbsent().
|
// FIXME: It could have been better if there is setAttachmentIfAbsent().
|
||||||
|
@ -198,7 +198,7 @@ public class ReadTimeoutHandler extends SimpleChannelUpstreamHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void destroy(ChannelHandlerContext ctx) {
|
private static void destroy(ChannelHandlerContext ctx) {
|
||||||
State state;
|
State state;
|
||||||
synchronized (ctx) {
|
synchronized (ctx) {
|
||||||
state = state(ctx);
|
state = state(ctx);
|
||||||
@ -211,7 +211,7 @@ public class ReadTimeoutHandler extends SimpleChannelUpstreamHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private State state(ChannelHandlerContext ctx) {
|
private static State state(ChannelHandlerContext ctx) {
|
||||||
State state;
|
State state;
|
||||||
synchronized (ctx) {
|
synchronized (ctx) {
|
||||||
// FIXME: It could have been better if there is setAttachmentIfAbsent().
|
// FIXME: It could have been better if there is setAttachmentIfAbsent().
|
||||||
|
@ -22,13 +22,13 @@ import java.util.concurrent.TimeUnit;
|
|||||||
import org.jboss.netty.bootstrap.ServerBootstrap;
|
import org.jboss.netty.bootstrap.ServerBootstrap;
|
||||||
import org.jboss.netty.channel.ChannelFuture;
|
import org.jboss.netty.channel.ChannelFuture;
|
||||||
import org.jboss.netty.channel.ChannelFutureListener;
|
import org.jboss.netty.channel.ChannelFutureListener;
|
||||||
|
import org.jboss.netty.channel.ChannelHandler.Sharable;
|
||||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||||
import org.jboss.netty.channel.ChannelPipeline;
|
import org.jboss.netty.channel.ChannelPipeline;
|
||||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||||
import org.jboss.netty.channel.Channels;
|
import org.jboss.netty.channel.Channels;
|
||||||
import org.jboss.netty.channel.MessageEvent;
|
import org.jboss.netty.channel.MessageEvent;
|
||||||
import org.jboss.netty.channel.SimpleChannelDownstreamHandler;
|
import org.jboss.netty.channel.SimpleChannelDownstreamHandler;
|
||||||
import org.jboss.netty.channel.ChannelHandler.Sharable;
|
|
||||||
import org.jboss.netty.util.ExternalResourceReleasable;
|
import org.jboss.netty.util.ExternalResourceReleasable;
|
||||||
import org.jboss.netty.util.HashedWheelTimer;
|
import org.jboss.netty.util.HashedWheelTimer;
|
||||||
import org.jboss.netty.util.Timeout;
|
import org.jboss.netty.util.Timeout;
|
||||||
@ -130,6 +130,13 @@ public class WriteTimeoutHandler extends SimpleChannelDownstreamHandler
|
|||||||
timer.stop();
|
timer.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the write timeout of the specified event. By default, this method returns the
|
||||||
|
* timeout value you specified in the constructor. Override this method to determine the
|
||||||
|
* timeout value depending on the message being written.
|
||||||
|
*
|
||||||
|
* @param e the message being written
|
||||||
|
*/
|
||||||
protected long getTimeoutMillis(MessageEvent e) {
|
protected long getTimeoutMillis(MessageEvent e) {
|
||||||
return timeoutMillis;
|
return timeoutMillis;
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ public final class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
|||||||
return segments[hash >>> segmentShift & segmentMask];
|
return segments[hash >>> segmentShift & segmentMask];
|
||||||
}
|
}
|
||||||
|
|
||||||
private int hashOf(Object key) {
|
private static int hashOf(Object key) {
|
||||||
return hash(key.hashCode());
|
return hash(key.hashCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,7 +270,7 @@ public final class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
|||||||
return new Segment[i];
|
return new Segment[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean keyEq(Object src, Object dest) {
|
private static boolean keyEq(Object src, Object dest) {
|
||||||
return src.equals(dest);
|
return src.equals(dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ public final class ConcurrentIdentityHashMap<K, V> extends AbstractMap<K, V>
|
|||||||
return segments[hash >>> segmentShift & segmentMask];
|
return segments[hash >>> segmentShift & segmentMask];
|
||||||
}
|
}
|
||||||
|
|
||||||
private int hashOf(Object key) {
|
private static int hashOf(Object key) {
|
||||||
return hash(System.identityHashCode(key));
|
return hash(System.identityHashCode(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,7 +270,7 @@ public final class ConcurrentIdentityHashMap<K, V> extends AbstractMap<K, V>
|
|||||||
return new Segment[i];
|
return new Segment[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean keyEq(Object src, Object dest) {
|
private static boolean keyEq(Object src, Object dest) {
|
||||||
return src == dest;
|
return src == dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ public final class ConcurrentIdentityWeakKeyHashMap<K, V> extends AbstractMap<K,
|
|||||||
return segments[hash >>> segmentShift & segmentMask];
|
return segments[hash >>> segmentShift & segmentMask];
|
||||||
}
|
}
|
||||||
|
|
||||||
private int hashOf(Object key) {
|
private static int hashOf(Object key) {
|
||||||
return hash(System.identityHashCode(key));
|
return hash(System.identityHashCode(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,7 +315,7 @@ public final class ConcurrentIdentityWeakKeyHashMap<K, V> extends AbstractMap<K,
|
|||||||
return new Segment[i];
|
return new Segment[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean keyEq(Object src, Object dest) {
|
private static boolean keyEq(Object src, Object dest) {
|
||||||
return src == dest;
|
return src == dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ public final class ConcurrentWeakKeyHashMap<K, V> extends AbstractMap<K, V> impl
|
|||||||
return segments[hash >>> segmentShift & segmentMask];
|
return segments[hash >>> segmentShift & segmentMask];
|
||||||
}
|
}
|
||||||
|
|
||||||
private int hashOf(Object key) {
|
private static int hashOf(Object key) {
|
||||||
return hash(key.hashCode());
|
return hash(key.hashCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,7 +315,7 @@ public final class ConcurrentWeakKeyHashMap<K, V> extends AbstractMap<K, V> impl
|
|||||||
return new Segment[i];
|
return new Segment[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean keyEq(Object src, Object dest) {
|
private static boolean keyEq(Object src, Object dest) {
|
||||||
return src.equals(dest);
|
return src.equals(dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1331,7 +1331,7 @@ public class LegacyLinkedTransferQueue<E> extends AbstractQueue<E>
|
|||||||
throws java.io.IOException, ClassNotFoundException {
|
throws java.io.IOException, ClassNotFoundException {
|
||||||
s.defaultReadObject();
|
s.defaultReadObject();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@SuppressWarnings("unchecked") E item = (E) s.readObject();
|
E item = (E) s.readObject();
|
||||||
if (item == null) {
|
if (item == null) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
@ -680,7 +680,7 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
|
|||||||
(t = tail) != null &&
|
(t = tail) != null &&
|
||||||
(s = t.next) != null && // advance and retry
|
(s = t.next) != null && // advance and retry
|
||||||
(s = s.next) != null && s != t) {
|
(s = s.next) != null && s != t) {
|
||||||
;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
@ -1383,7 +1383,6 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
|
|||||||
throws java.io.IOException, ClassNotFoundException {
|
throws java.io.IOException, ClassNotFoundException {
|
||||||
s.defaultReadObject();
|
s.defaultReadObject();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
E item = (E) s.readObject();
|
E item = (E) s.readObject();
|
||||||
if (item == null) {
|
if (item == null) {
|
||||||
break;
|
break;
|
||||||
|
@ -460,7 +460,7 @@ final class InfCodes {
|
|||||||
// at least ten. The ten bytes are six bytes for the longest length/
|
// at least ten. The ten bytes are six bytes for the longest length/
|
||||||
// distance pair plus four bytes for overloading the bit buffer.
|
// distance pair plus four bytes for overloading the bit buffer.
|
||||||
|
|
||||||
int inflate_fast(int bl, int bd, int[] tl, int tl_index, int[] td,
|
static int inflate_fast(int bl, int bd, int[] tl, int tl_index, int[] td,
|
||||||
int td_index, InfBlocks s, ZStream z) {
|
int td_index, InfBlocks s, ZStream z) {
|
||||||
int t; // temporary pointer
|
int t; // temporary pointer
|
||||||
int[] tp; // temporary pointer
|
int[] tp; // temporary pointer
|
||||||
|
@ -562,7 +562,7 @@ final class Inflate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int inflateSetDictionary(ZStream z, byte[] dictionary, int dictLength) {
|
static int inflateSetDictionary(ZStream z, byte[] dictionary, int dictLength) {
|
||||||
int index = 0;
|
int index = 0;
|
||||||
int length = dictLength;
|
int length = dictLength;
|
||||||
if (z == null || z.istate == null || z.istate.mode != DICT0) {
|
if (z == null || z.istate == null || z.istate.mode != DICT0) {
|
||||||
|
@ -109,7 +109,7 @@ public final class ZStream {
|
|||||||
if (istate == null) {
|
if (istate == null) {
|
||||||
return JZlib.Z_STREAM_ERROR;
|
return JZlib.Z_STREAM_ERROR;
|
||||||
}
|
}
|
||||||
return istate.inflateSetDictionary(this, dictionary, dictLength);
|
return Inflate.inflateSetDictionary(this, dictionary, dictLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int deflateInit(int level) {
|
public int deflateInit(int level) {
|
||||||
|
@ -35,12 +35,12 @@ import org.junit.Test;
|
|||||||
public class ChunkedWriteHandlerTest {
|
public class ChunkedWriteHandlerTest {
|
||||||
private static final byte[] BYTES = new byte[1024 * 64];
|
private static final byte[] BYTES = new byte[1024 * 64];
|
||||||
private static final File TMP;
|
private static final File TMP;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
for (int i = 0; i < BYTES.length; i++) {
|
for (int i = 0; i < BYTES.length; i++) {
|
||||||
BYTES[i] = (byte) i;
|
BYTES[i] = (byte) i;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileOutputStream out = null;
|
FileOutputStream out = null;
|
||||||
try {
|
try {
|
||||||
TMP = File.createTempFile("netty-chunk-", ".tmp");
|
TMP = File.createTempFile("netty-chunk-", ".tmp");
|
||||||
@ -65,35 +65,35 @@ public class ChunkedWriteHandlerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testChunkedStream() {
|
public void testChunkedStream() {
|
||||||
check(new ChunkedStream(new ByteArrayInputStream(BYTES)));
|
check(new ChunkedStream(new ByteArrayInputStream(BYTES)));
|
||||||
|
|
||||||
check(new ChunkedStream(new ByteArrayInputStream(BYTES)), new ChunkedStream(new ByteArrayInputStream(BYTES)), new ChunkedStream(new ByteArrayInputStream(BYTES)));
|
check(new ChunkedStream(new ByteArrayInputStream(BYTES)), new ChunkedStream(new ByteArrayInputStream(BYTES)), new ChunkedStream(new ByteArrayInputStream(BYTES)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testChunkedNioStream() {
|
public void testChunkedNioStream() {
|
||||||
check(new ChunkedNioStream(Channels.newChannel(new ByteArrayInputStream(BYTES))));
|
check(new ChunkedNioStream(Channels.newChannel(new ByteArrayInputStream(BYTES))));
|
||||||
|
|
||||||
check(new ChunkedNioStream(Channels.newChannel(new ByteArrayInputStream(BYTES))), new ChunkedNioStream(Channels.newChannel(new ByteArrayInputStream(BYTES))), new ChunkedNioStream(Channels.newChannel(new ByteArrayInputStream(BYTES))));
|
check(new ChunkedNioStream(Channels.newChannel(new ByteArrayInputStream(BYTES))), new ChunkedNioStream(Channels.newChannel(new ByteArrayInputStream(BYTES))), new ChunkedNioStream(Channels.newChannel(new ByteArrayInputStream(BYTES))));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testChunkedFile() throws IOException {
|
public void testChunkedFile() throws IOException {
|
||||||
check(new ChunkedFile(TMP));
|
check(new ChunkedFile(TMP));
|
||||||
|
|
||||||
check(new ChunkedFile(TMP), new ChunkedFile(TMP), new ChunkedFile(TMP));
|
check(new ChunkedFile(TMP), new ChunkedFile(TMP), new ChunkedFile(TMP));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testChunkedNioFile() throws IOException {
|
public void testChunkedNioFile() throws IOException {
|
||||||
check(new ChunkedNioFile(TMP));
|
check(new ChunkedNioFile(TMP));
|
||||||
|
|
||||||
check(new ChunkedNioFile(TMP), new ChunkedNioFile(TMP), new ChunkedNioFile(TMP));
|
check(new ChunkedNioFile(TMP), new ChunkedNioFile(TMP), new ChunkedNioFile(TMP));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void check(ChunkedInput... inputs) {
|
private static void check(ChunkedInput... inputs) {
|
||||||
EncoderEmbedder<ChannelBuffer> embedder = new EncoderEmbedder<ChannelBuffer>(new ChunkedWriteHandler());
|
EncoderEmbedder<ChannelBuffer> embedder = new EncoderEmbedder<ChannelBuffer>(new ChunkedWriteHandler());
|
||||||
for (ChunkedInput input: inputs) {
|
for (ChunkedInput input: inputs) {
|
||||||
embedder.offer(input);
|
embedder.offer(input);
|
||||||
|
@ -15,18 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.jboss.netty.channel.socket;
|
package org.jboss.netty.channel.socket;
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.*;
|
||||||
import org.jboss.netty.bootstrap.ConnectionlessBootstrap;
|
|
||||||
import org.jboss.netty.buffer.ChannelBuffer;
|
|
||||||
import org.jboss.netty.buffer.ChannelBuffers;
|
|
||||||
import org.jboss.netty.channel.Channel;
|
|
||||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
|
||||||
import org.jboss.netty.channel.MessageEvent;
|
|
||||||
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
|
||||||
import org.jboss.netty.channel.socket.DatagramChannel;
|
|
||||||
import org.jboss.netty.channel.socket.DatagramChannelFactory;
|
|
||||||
import org.jboss.netty.util.TestUtil;
|
|
||||||
import org.jboss.netty.util.internal.ExecutorUtil;
|
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
@ -37,6 +26,15 @@ import java.util.concurrent.ExecutorService;
|
|||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.jboss.netty.bootstrap.ConnectionlessBootstrap;
|
||||||
|
import org.jboss.netty.buffer.ChannelBuffer;
|
||||||
|
import org.jboss.netty.buffer.ChannelBuffers;
|
||||||
|
import org.jboss.netty.channel.Channel;
|
||||||
|
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||||
|
import org.jboss.netty.channel.MessageEvent;
|
||||||
|
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
||||||
|
import org.jboss.netty.util.TestUtil;
|
||||||
|
import org.jboss.netty.util.internal.ExecutorUtil;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
@ -66,14 +64,14 @@ public abstract class AbstractDatagramMulticastTest {
|
|||||||
ConnectionlessBootstrap sb = new ConnectionlessBootstrap(newServerSocketChannelFactory(executor));
|
ConnectionlessBootstrap sb = new ConnectionlessBootstrap(newServerSocketChannelFactory(executor));
|
||||||
ConnectionlessBootstrap cb = new ConnectionlessBootstrap(newClientSocketChannelFactory(executor));
|
ConnectionlessBootstrap cb = new ConnectionlessBootstrap(newClientSocketChannelFactory(executor));
|
||||||
MulticastTestHandler mhandler = new MulticastTestHandler();
|
MulticastTestHandler mhandler = new MulticastTestHandler();
|
||||||
|
|
||||||
cb.getPipeline().addFirst("handler", mhandler);
|
cb.getPipeline().addFirst("handler", mhandler);
|
||||||
sb.getPipeline().addFirst("handler", new SimpleChannelUpstreamHandler());
|
sb.getPipeline().addFirst("handler", new SimpleChannelUpstreamHandler());
|
||||||
|
|
||||||
int port = TestUtil.getFreePort();
|
int port = TestUtil.getFreePort();
|
||||||
|
|
||||||
NetworkInterface iface = NetworkInterface.getByInetAddress(InetAddress.getLocalHost());
|
NetworkInterface iface = NetworkInterface.getByInetAddress(InetAddress.getLocalHost());
|
||||||
|
|
||||||
// check if the NetworkInterface is null, this is the case on my ubuntu dev machine but not on osx and windows.
|
// check if the NetworkInterface is null, this is the case on my ubuntu dev machine but not on osx and windows.
|
||||||
// if so fail back the the first interface
|
// if so fail back the the first interface
|
||||||
if (iface == null) {
|
if (iface == null) {
|
||||||
@ -82,10 +80,10 @@ public abstract class AbstractDatagramMulticastTest {
|
|||||||
}
|
}
|
||||||
sb.setOption("networkInterface", iface);
|
sb.setOption("networkInterface", iface);
|
||||||
sb.setOption("reuseAddress", true);
|
sb.setOption("reuseAddress", true);
|
||||||
|
|
||||||
Channel sc = sb.bind(new InetSocketAddress(port));
|
Channel sc = sb.bind(new InetSocketAddress(port));
|
||||||
|
|
||||||
|
|
||||||
String group = "230.0.0.1";
|
String group = "230.0.0.1";
|
||||||
InetSocketAddress groupAddress = new InetSocketAddress(group, port);
|
InetSocketAddress groupAddress = new InetSocketAddress(group, port);
|
||||||
|
|
||||||
@ -93,14 +91,14 @@ public abstract class AbstractDatagramMulticastTest {
|
|||||||
cb.setOption("reuseAddress", true);
|
cb.setOption("reuseAddress", true);
|
||||||
|
|
||||||
DatagramChannel cc = (DatagramChannel) cb.bind(new InetSocketAddress(port));
|
DatagramChannel cc = (DatagramChannel) cb.bind(new InetSocketAddress(port));
|
||||||
|
|
||||||
assertTrue(cc.joinGroup(groupAddress, iface).awaitUninterruptibly().isSuccess());
|
assertTrue(cc.joinGroup(groupAddress, iface).awaitUninterruptibly().isSuccess());
|
||||||
|
|
||||||
assertTrue(sc.write(wrapInt(1), groupAddress).awaitUninterruptibly().isSuccess());
|
assertTrue(sc.write(wrapInt(1), groupAddress).awaitUninterruptibly().isSuccess());
|
||||||
|
|
||||||
|
|
||||||
assertTrue(mhandler.await());
|
assertTrue(mhandler.await());
|
||||||
|
|
||||||
assertTrue(sc.write(wrapInt(1), groupAddress).awaitUninterruptibly().isSuccess());
|
assertTrue(sc.write(wrapInt(1), groupAddress).awaitUninterruptibly().isSuccess());
|
||||||
|
|
||||||
|
|
||||||
@ -109,42 +107,42 @@ public abstract class AbstractDatagramMulticastTest {
|
|||||||
|
|
||||||
// sleep a second to make sure we left the group
|
// sleep a second to make sure we left the group
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
|
|
||||||
// we should not receive a message anymore as we left the group before
|
// we should not receive a message anymore as we left the group before
|
||||||
assertTrue(sc.write(wrapInt(1), groupAddress).awaitUninterruptibly().isSuccess());
|
assertTrue(sc.write(wrapInt(1), groupAddress).awaitUninterruptibly().isSuccess());
|
||||||
|
|
||||||
sc.close().awaitUninterruptibly();
|
sc.close().awaitUninterruptibly();
|
||||||
cc.close().awaitUninterruptibly();
|
cc.close().awaitUninterruptibly();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChannelBuffer wrapInt(int value) {
|
private static ChannelBuffer wrapInt(int value) {
|
||||||
ChannelBuffer buf = ChannelBuffers.buffer(4);
|
ChannelBuffer buf = ChannelBuffers.buffer(4);
|
||||||
buf.writeInt(value);
|
buf.writeInt(value);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class MulticastTestHandler extends SimpleChannelUpstreamHandler {
|
private final class MulticastTestHandler extends SimpleChannelUpstreamHandler {
|
||||||
private final CountDownLatch latch = new CountDownLatch(1);
|
private final CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
|
||||||
private boolean done = false;
|
private boolean done = false;
|
||||||
private volatile boolean fail = false;
|
private volatile boolean fail = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
||||||
super.messageReceived(ctx, e);
|
super.messageReceived(ctx, e);
|
||||||
if (done) {
|
if (done) {
|
||||||
fail = true;
|
fail = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.assertEquals(1,((ChannelBuffer)e.getMessage()).readInt());
|
Assert.assertEquals(1,((ChannelBuffer)e.getMessage()).readInt());
|
||||||
|
|
||||||
latch.countDown();
|
latch.countDown();
|
||||||
|
|
||||||
// mark the handler as done as we only are supposed to receive one message
|
// mark the handler as done as we only are supposed to receive one message
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean await() throws Exception {
|
public boolean await() throws Exception {
|
||||||
boolean success = latch.await(10, TimeUnit.SECONDS);
|
boolean success = latch.await(10, TimeUnit.SECONDS);
|
||||||
if (fail) {
|
if (fail) {
|
||||||
@ -153,6 +151,6 @@ public abstract class AbstractDatagramMulticastTest {
|
|||||||
}
|
}
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,9 +18,9 @@ package org.jboss.netty.handler.codec.spdy;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.jboss.netty.channel.Channels;
|
|
||||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||||
import org.jboss.netty.channel.ChannelStateEvent;
|
import org.jboss.netty.channel.ChannelStateEvent;
|
||||||
|
import org.jboss.netty.channel.Channels;
|
||||||
import org.jboss.netty.channel.MessageEvent;
|
import org.jboss.netty.channel.MessageEvent;
|
||||||
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
|
||||||
import org.jboss.netty.handler.codec.embedder.DecoderEmbedder;
|
import org.jboss.netty.handler.codec.embedder.DecoderEmbedder;
|
||||||
@ -36,7 +36,7 @@ public class SpdySessionHandlerTest {
|
|||||||
closeMessage.setValue(closeSignal, 0);
|
closeMessage.setValue(closeSignal, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertHeaderBlock(SpdyHeaderBlock received, SpdyHeaderBlock expected) {
|
private static void assertHeaderBlock(SpdyHeaderBlock received, SpdyHeaderBlock expected) {
|
||||||
for (String name: expected.getHeaderNames()) {
|
for (String name: expected.getHeaderNames()) {
|
||||||
List<String> expectedValues = expected.getHeaders(name);
|
List<String> expectedValues = expected.getHeaders(name);
|
||||||
List<String> receivedValues = received.getHeaders(name);
|
List<String> receivedValues = received.getHeaders(name);
|
||||||
@ -48,7 +48,7 @@ public class SpdySessionHandlerTest {
|
|||||||
Assert.assertTrue(received.getHeaders().isEmpty());
|
Assert.assertTrue(received.getHeaders().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertDataFrame(Object msg, int streamID, boolean last) {
|
private static void assertDataFrame(Object msg, int streamID, boolean last) {
|
||||||
Assert.assertNotNull(msg);
|
Assert.assertNotNull(msg);
|
||||||
Assert.assertTrue(msg instanceof SpdyDataFrame);
|
Assert.assertTrue(msg instanceof SpdyDataFrame);
|
||||||
SpdyDataFrame spdyDataFrame = (SpdyDataFrame) msg;
|
SpdyDataFrame spdyDataFrame = (SpdyDataFrame) msg;
|
||||||
@ -56,7 +56,7 @@ public class SpdySessionHandlerTest {
|
|||||||
Assert.assertTrue(spdyDataFrame.isLast() == last);
|
Assert.assertTrue(spdyDataFrame.isLast() == last);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertSynReply(Object msg, int streamID, boolean last, SpdyHeaderBlock headers) {
|
private static void assertSynReply(Object msg, int streamID, boolean last, SpdyHeaderBlock headers) {
|
||||||
Assert.assertNotNull(msg);
|
Assert.assertNotNull(msg);
|
||||||
Assert.assertTrue(msg instanceof SpdySynReplyFrame);
|
Assert.assertTrue(msg instanceof SpdySynReplyFrame);
|
||||||
SpdySynReplyFrame spdySynReplyFrame = (SpdySynReplyFrame) msg;
|
SpdySynReplyFrame spdySynReplyFrame = (SpdySynReplyFrame) msg;
|
||||||
@ -65,7 +65,7 @@ public class SpdySessionHandlerTest {
|
|||||||
assertHeaderBlock(spdySynReplyFrame, headers);
|
assertHeaderBlock(spdySynReplyFrame, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertRstStream(Object msg, int streamID, SpdyStreamStatus status) {
|
private static void assertRstStream(Object msg, int streamID, SpdyStreamStatus status) {
|
||||||
Assert.assertNotNull(msg);
|
Assert.assertNotNull(msg);
|
||||||
Assert.assertTrue(msg instanceof SpdyRstStreamFrame);
|
Assert.assertTrue(msg instanceof SpdyRstStreamFrame);
|
||||||
SpdyRstStreamFrame spdyRstStreamFrame = (SpdyRstStreamFrame) msg;
|
SpdyRstStreamFrame spdyRstStreamFrame = (SpdyRstStreamFrame) msg;
|
||||||
@ -73,21 +73,21 @@ public class SpdySessionHandlerTest {
|
|||||||
Assert.assertTrue(spdyRstStreamFrame.getStatus().equals(status));
|
Assert.assertTrue(spdyRstStreamFrame.getStatus().equals(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertPing(Object msg, int ID) {
|
private static void assertPing(Object msg, int ID) {
|
||||||
Assert.assertNotNull(msg);
|
Assert.assertNotNull(msg);
|
||||||
Assert.assertTrue(msg instanceof SpdyPingFrame);
|
Assert.assertTrue(msg instanceof SpdyPingFrame);
|
||||||
SpdyPingFrame spdyPingFrame = (SpdyPingFrame) msg;
|
SpdyPingFrame spdyPingFrame = (SpdyPingFrame) msg;
|
||||||
Assert.assertTrue(spdyPingFrame.getID() == ID);
|
Assert.assertTrue(spdyPingFrame.getID() == ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertGoAway(Object msg, int lastGoodStreamID) {
|
private static void assertGoAway(Object msg, int lastGoodStreamID) {
|
||||||
Assert.assertNotNull(msg);
|
Assert.assertNotNull(msg);
|
||||||
Assert.assertTrue(msg instanceof SpdyGoAwayFrame);
|
Assert.assertTrue(msg instanceof SpdyGoAwayFrame);
|
||||||
SpdyGoAwayFrame spdyGoAwayFrame = (SpdyGoAwayFrame) msg;
|
SpdyGoAwayFrame spdyGoAwayFrame = (SpdyGoAwayFrame) msg;
|
||||||
Assert.assertTrue(spdyGoAwayFrame.getLastGoodStreamID() == lastGoodStreamID);
|
Assert.assertTrue(spdyGoAwayFrame.getLastGoodStreamID() == lastGoodStreamID);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertHeaders(Object msg, int streamID, SpdyHeaderBlock headers) {
|
private static void assertHeaders(Object msg, int streamID, SpdyHeaderBlock headers) {
|
||||||
Assert.assertNotNull(msg);
|
Assert.assertNotNull(msg);
|
||||||
Assert.assertTrue(msg instanceof SpdyHeadersFrame);
|
Assert.assertTrue(msg instanceof SpdyHeadersFrame);
|
||||||
SpdyHeadersFrame spdyHeadersFrame = (SpdyHeadersFrame) msg;
|
SpdyHeadersFrame spdyHeadersFrame = (SpdyHeadersFrame) msg;
|
||||||
@ -263,8 +263,8 @@ public class SpdySessionHandlerTest {
|
|||||||
// Echo Handler opens 4 half-closed streams on session connection
|
// Echo Handler opens 4 half-closed streams on session connection
|
||||||
// and then sets the number of concurrent streams to 3
|
// and then sets the number of concurrent streams to 3
|
||||||
private class EchoHandler extends SimpleChannelUpstreamHandler {
|
private class EchoHandler extends SimpleChannelUpstreamHandler {
|
||||||
private int closeSignal;
|
private final int closeSignal;
|
||||||
private boolean server;
|
private final boolean server;
|
||||||
|
|
||||||
EchoHandler(int closeSignal, boolean server) {
|
EchoHandler(int closeSignal, boolean server) {
|
||||||
super();
|
super();
|
||||||
@ -299,9 +299,9 @@ public class SpdySessionHandlerTest {
|
|||||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
|
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
Object msg = e.getMessage();
|
Object msg = e.getMessage();
|
||||||
if ((msg instanceof SpdyDataFrame) ||
|
if (msg instanceof SpdyDataFrame ||
|
||||||
(msg instanceof SpdyPingFrame) ||
|
msg instanceof SpdyPingFrame ||
|
||||||
(msg instanceof SpdyHeadersFrame)) {
|
msg instanceof SpdyHeadersFrame) {
|
||||||
|
|
||||||
Channels.write(e.getChannel(), msg, e.getRemoteAddress());
|
Channels.write(e.getChannel(), msg, e.getRemoteAddress());
|
||||||
return;
|
return;
|
||||||
|
@ -66,7 +66,7 @@ public class StringUtilTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertStripped(final char controlCode) {
|
private static void assertStripped(final char controlCode) {
|
||||||
final Object object = "aaa" + controlCode + "bbb";
|
final Object object = "aaa" + controlCode + "bbb";
|
||||||
final String stripped = StringUtil.stripControlCharacters(object);
|
final String stripped = StringUtil.stripControlCharacters(object);
|
||||||
assertEquals("aaa bbb", stripped);
|
assertEquals("aaa bbb", stripped);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user