Moved http tunnel implementation into org.jboss.netty.channel.socket.http package, replacing the original implementation.

Existing usage example has been deleted and should be replaced by an updated example using the new API.
This commit is contained in:
iainmcgin 2011-04-08 12:37:39 +01:00 committed by Trustin Lee
parent 12d2c8ad2e
commit f7729bc8bb
65 changed files with 63 additions and 1386 deletions

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.net.InetSocketAddress;
import java.net.SocketAddress;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.util.HashSet;
import java.util.Set;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.security.SecureRandom;

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import static org.jboss.netty.channel.Channels.fireChannelBound;
import static org.jboss.netty.channel.Channels.fireChannelConnected;

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
/**
* Configuration the server end of an http tunnel.

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.net.InetSocketAddress;

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import org.jboss.netty.buffer.ChannelBuffer;

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.util.concurrent.atomic.AtomicBoolean;

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import org.jboss.netty.channel.DefaultChannelConfig;
import org.jboss.netty.channel.socket.SocketChannelConfig;

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.net.InetSocketAddress;
import java.net.SocketAddress;

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.net.SocketAddress;

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.group.ChannelGroup;

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.net.InetSocketAddress;

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.net.InetSocketAddress;

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.net.InetSocketAddress;

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.util.Map;
import java.util.Map.Entry;

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.Channels;

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.net.SocketAddress;

View File

@ -1,418 +0,0 @@
/*
* Copyright 2009 Red Hat, Inc.
*
* Red Hat licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.http;
import static org.jboss.netty.channel.Channels.*;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.channels.NotYetConnectedException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.AbstractChannel;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.DefaultChannelPipeline;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.channel.socket.ClientSocketChannelFactory;
import org.jboss.netty.channel.socket.SocketChannel;
import org.jboss.netty.handler.codec.http.DefaultHttpChunk;
import org.jboss.netty.handler.codec.http.DefaultHttpRequest;
import org.jboss.netty.handler.codec.http.HttpChunk;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.jboss.netty.handler.codec.http.HttpMethod;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpRequestEncoder;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.handler.codec.http.HttpResponseDecoder;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.jboss.netty.handler.codec.http.HttpVersion;
import org.jboss.netty.handler.ssl.SslHandler;
/**
* @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
* @author Andy Taylor (andy.taylor@jboss.org)
* @author <a href="http://gleamynode.net/">Trustin Lee</a>
* @version $Rev$, $Date$
*/
class HttpTunnelingClientSocketChannel extends AbstractChannel
implements org.jboss.netty.channel.socket.SocketChannel {
final HttpTunnelingSocketChannelConfig config;
volatile boolean requestHeaderWritten;
final Object interestOpsLock = new Object();
final SocketChannel realChannel;
private final HttpTunnelingClientSocketChannel.ServletChannelHandler handler = new ServletChannelHandler();
HttpTunnelingClientSocketChannel(
ChannelFactory factory,
ChannelPipeline pipeline,
ChannelSink sink, ClientSocketChannelFactory clientSocketChannelFactory) {
super(null, factory, pipeline, sink);
config = new HttpTunnelingSocketChannelConfig(this);
DefaultChannelPipeline channelPipeline = new DefaultChannelPipeline();
channelPipeline.addLast("decoder", new HttpResponseDecoder());
channelPipeline.addLast("encoder", new HttpRequestEncoder());
channelPipeline.addLast("handler", handler);
realChannel = clientSocketChannelFactory.newChannel(channelPipeline);
fireChannelOpen(this);
}
@Override
public HttpTunnelingSocketChannelConfig getConfig() {
return config;
}
@Override
public InetSocketAddress getLocalAddress() {
return realChannel.getLocalAddress();
}
@Override
public InetSocketAddress getRemoteAddress() {
return realChannel.getRemoteAddress();
}
@Override
public boolean isBound() {
return realChannel.isBound();
}
@Override
public boolean isConnected() {
return realChannel.isConnected();
}
@Override
public int getInterestOps() {
return realChannel.getInterestOps();
}
@Override
public boolean isWritable() {
return realChannel.isWritable();
}
@Override
protected boolean setClosed() {
return super.setClosed();
}
@Override
public ChannelFuture write(Object message, SocketAddress remoteAddress) {
if (remoteAddress == null || remoteAddress.equals(getRemoteAddress())) {
return super.write(message, null);
}
else {
return getUnsupportedOperationFuture();
}
}
void bindReal(final SocketAddress localAddress, final ChannelFuture future) {
realChannel.bind(localAddress).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture f) {
if (f.isSuccess()) {
future.setSuccess();
} else {
future.setFailure(f.getCause());
}
}
});
}
void connectReal(final SocketAddress remoteAddress, final ChannelFuture future) {
final SocketChannel virtualChannel = this;
realChannel.connect(remoteAddress).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture f) {
final String serverName = config.getServerName();
final int serverPort = ((InetSocketAddress) remoteAddress).getPort();
final String serverPath = config.getServerPath();
if (f.isSuccess()) {
// Configure SSL
SSLContext sslContext = config.getSslContext();
ChannelFuture sslHandshakeFuture = null;
if (sslContext != null) {
// Create a new SSLEngine from the specified SSLContext.
SSLEngine engine;
if (serverName != null) {
engine = sslContext.createSSLEngine(serverName, serverPort);
} else {
engine = sslContext.createSSLEngine();
}
// Configure the SSLEngine.
engine.setUseClientMode(true);
engine.setEnableSessionCreation(config.isEnableSslSessionCreation());
String[] enabledCipherSuites = config.getEnabledSslCipherSuites();
if (enabledCipherSuites != null) {
engine.setEnabledCipherSuites(enabledCipherSuites);
}
String[] enabledProtocols = config.getEnabledSslProtocols();
if (enabledProtocols != null) {
engine.setEnabledProtocols(enabledProtocols);
}
SslHandler sslHandler = new SslHandler(engine);
realChannel.getPipeline().addFirst("ssl", sslHandler);
sslHandshakeFuture = sslHandler.handshake();
}
// Send the HTTP request.
final HttpRequest req = new DefaultHttpRequest(
HttpVersion.HTTP_1_1, HttpMethod.POST, serverPath);
if (serverName != null) {
req.setHeader(HttpHeaders.Names.HOST, serverName);
}
req.setHeader(HttpHeaders.Names.CONTENT_TYPE, "application/octet-stream");
req.setHeader(HttpHeaders.Names.TRANSFER_ENCODING, HttpHeaders.Values.CHUNKED);
req.setHeader(HttpHeaders.Names.CONTENT_TRANSFER_ENCODING, HttpHeaders.Values.BINARY);
req.setHeader(HttpHeaders.Names.USER_AGENT, HttpTunnelingClientSocketChannel.class.getName());
if (sslHandshakeFuture == null) {
realChannel.write(req);
requestHeaderWritten = true;
future.setSuccess();
fireChannelConnected(virtualChannel, remoteAddress);
} else {
sslHandshakeFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture f) {
if (f.isSuccess()) {
realChannel.write(req);
requestHeaderWritten = true;
future.setSuccess();
fireChannelConnected(virtualChannel, remoteAddress);
} else {
future.setFailure(f.getCause());
fireExceptionCaught(virtualChannel, f.getCause());
}
}
});
}
} else {
future.setFailure(f.getCause());
fireExceptionCaught(virtualChannel, f.getCause());
}
}
});
}
void writeReal(final ChannelBuffer a, final ChannelFuture future) {
if (!requestHeaderWritten) {
throw new NotYetConnectedException();
}
final int size = a.readableBytes();
final ChannelFuture f;
if (size == 0) {
f = realChannel.write(ChannelBuffers.EMPTY_BUFFER);
} else {
f = realChannel.write(new DefaultHttpChunk(a));
}
f.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture f) {
if (f.isSuccess()) {
future.setSuccess();
if (size != 0) {
fireWriteComplete(HttpTunnelingClientSocketChannel.this, size);
}
} else {
future.setFailure(f.getCause());
}
}
});
}
private ChannelFuture writeLastChunk() {
if (!requestHeaderWritten) {
throw new NotYetConnectedException();
} else {
return realChannel.write(HttpChunk.LAST_CHUNK);
}
}
void setInterestOpsReal(final int interestOps, final ChannelFuture future) {
realChannel.setInterestOps(interestOps).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture f) {
if (f.isSuccess()) {
future.setSuccess();
} else {
future.setFailure(f.getCause());
}
}
});
}
void disconnectReal(final ChannelFuture future) {
writeLastChunk().addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture f) {
realChannel.disconnect().addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture f) {
if (f.isSuccess()) {
future.setSuccess();
} else {
future.setFailure(f.getCause());
}
}
});
}
});
}
void unbindReal(final ChannelFuture future) {
writeLastChunk().addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture f) {
realChannel.unbind().addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture f) {
if (f.isSuccess()) {
future.setSuccess();
} else {
future.setFailure(f.getCause());
}
}
});
}
});
}
void closeReal(final ChannelFuture future) {
writeLastChunk().addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture f) {
realChannel.close().addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture f) {
// Note: If 'future' refers to the closeFuture,
// setSuccess() and setFailure() do nothing.
// AbstractChannel.setClosed() should be called instead.
// (See AbstractChannel.ChannelCloseFuture)
if (f.isSuccess()) {
future.setSuccess();
} else {
future.setFailure(f.getCause());
}
// Notify the closeFuture.
setClosed();
}
});
}
});
}
final class ServletChannelHandler extends SimpleChannelUpstreamHandler {
private volatile boolean readingChunks;
final SocketChannel virtualChannel = HttpTunnelingClientSocketChannel.this;
@Override
public void channelBound(ChannelHandlerContext ctx, ChannelStateEvent e)
throws Exception {
fireChannelBound(virtualChannel, (SocketAddress) e.getValue());
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
if (!readingChunks) {
HttpResponse res = (HttpResponse) e.getMessage();
if (res.getStatus().getCode() != HttpResponseStatus.OK.getCode()) {
throw new ChannelException("Unexpected HTTP response status: " + res.getStatus());
}
if (res.isChunked()) {
readingChunks = true;
} else {
ChannelBuffer content = res.getContent();
if (content.readable()) {
fireMessageReceived(HttpTunnelingClientSocketChannel.this, content);
}
// Reached to the end of response - close the request.
closeReal(succeededFuture(virtualChannel));
}
} else {
HttpChunk chunk = (HttpChunk) e.getMessage();
if (!chunk.isLast()) {
fireMessageReceived(HttpTunnelingClientSocketChannel.this, chunk.getContent());
} else {
readingChunks = false;
// Reached to the end of response - close the request.
closeReal(succeededFuture(virtualChannel));
}
}
}
@Override
public void channelInterestChanged(ChannelHandlerContext ctx,
ChannelStateEvent e) throws Exception {
fireChannelInterestChanged(virtualChannel);
}
@Override
public void channelDisconnected(ChannelHandlerContext ctx,
ChannelStateEvent e) throws Exception {
fireChannelDisconnected(virtualChannel);
}
@Override
public void channelUnbound(ChannelHandlerContext ctx,
ChannelStateEvent e) throws Exception {
fireChannelUnbound(virtualChannel);
}
@Override
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)
throws Exception {
fireChannelClosed(virtualChannel);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
fireExceptionCaught(virtualChannel, e.getCause());
realChannel.close();
}
}
}

View File

@ -1,58 +0,0 @@
/*
* Copyright 2009 Red Hat, Inc.
*
* Red Hat licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.http;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.channel.socket.ClientSocketChannelFactory;
import org.jboss.netty.channel.socket.SocketChannel;
/**
* Creates a client-side {@link SocketChannel} which connects to an
* {@link HttpTunnelingServlet} to communicate with the server application
* behind the {@link HttpTunnelingServlet}. Please refer to the
* <a href="package-summary.html#package_description">package summary</a> for
* the detailed usage.
*
* @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
* @author Andy Taylor (andy.taylor@jboss.org)
* @author <a href="http://gleamynode.net/">Trustin Lee</a>
* @version $Rev$, $Date$
*
* @apiviz.landmark
*/
public class HttpTunnelingClientSocketChannelFactory implements ClientSocketChannelFactory {
private final ChannelSink sink = new HttpTunnelingClientSocketPipelineSink();
private final ClientSocketChannelFactory clientSocketChannelFactory;
/**
* Creates a new instance.
*/
public HttpTunnelingClientSocketChannelFactory(ClientSocketChannelFactory clientSocketChannelFactory) {
this.clientSocketChannelFactory = clientSocketChannelFactory;
}
@Override
public SocketChannel newChannel(ChannelPipeline pipeline) {
return new HttpTunnelingClientSocketChannel(this, pipeline, sink, clientSocketChannelFactory);
}
@Override
public void releaseExternalResources() {
clientSocketChannelFactory.releaseExternalResources();
}
}

View File

@ -1,78 +0,0 @@
/*
* Copyright 2009 Red Hat, Inc.
*
* Red Hat licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.http;
import java.net.SocketAddress;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.AbstractChannelSink;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelState;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.MessageEvent;
/**
* @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
* @author Andy Taylor (andy.taylor@jboss.org)
* @author <a href="http://gleamynode.net/">Trustin Lee</a>
* @version $Rev$, $Date$
*/
final class HttpTunnelingClientSocketPipelineSink extends AbstractChannelSink {
HttpTunnelingClientSocketPipelineSink() {
super();
}
@Override
public void eventSunk(
ChannelPipeline pipeline, ChannelEvent e) throws Exception {
HttpTunnelingClientSocketChannel channel = (HttpTunnelingClientSocketChannel) e.getChannel();
ChannelFuture future = e.getFuture();
if (e instanceof ChannelStateEvent) {
ChannelStateEvent stateEvent = (ChannelStateEvent) e;
ChannelState state = stateEvent.getState();
Object value = stateEvent.getValue();
switch (state) {
case OPEN:
if (Boolean.FALSE.equals(value)) {
channel.closeReal(future);
}
break;
case BOUND:
if (value != null) {
channel.bindReal((SocketAddress) value, future);
} else {
channel.unbindReal(future);
}
break;
case CONNECTED:
if (value != null) {
channel.connectReal((SocketAddress) value, future);
} else {
channel.closeReal(future);
}
break;
case INTEREST_OPS:
channel.setInterestOpsReal(((Integer) value).intValue(), future);
break;
}
} else if (e instanceof MessageEvent) {
channel.writeReal(((ChannelBuffer) ((MessageEvent) e).getMessage()), future);
}
}
}

View File

@ -1,246 +0,0 @@
/*
* Copyright 2009 Red Hat, Inc.
*
* Red Hat licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.http;
import java.io.EOFException;
import java.io.IOException;
import java.io.PushbackInputStream;
import java.net.SocketAddress;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.channel.local.DefaultLocalClientChannelFactory;
import org.jboss.netty.channel.local.LocalAddress;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
/**
* An {@link HttpServlet} that proxies an incoming data to the actual server
* and vice versa. Please refer to the
* <a href="package-summary.html#package_description">package summary</a> for
* the detailed usage.
*
* @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
* @author Andy Taylor (andy.taylor@jboss.org)
* @author <a href="http://gleamynode.net/">Trustin Lee</a>
* @version $Rev$, $Date$
*
* @apiviz.landmark
*/
public class HttpTunnelingServlet extends HttpServlet {
private static final long serialVersionUID = 4259910275899756070L;
private static final String ENDPOINT = "endpoint";
static final InternalLogger logger = InternalLoggerFactory.getInstance(HttpTunnelingServlet.class);
private volatile SocketAddress remoteAddress;
private volatile ChannelFactory channelFactory;
@Override
public void init() throws ServletException {
ServletConfig config = getServletConfig();
String endpoint = config.getInitParameter(ENDPOINT);
if (endpoint == null) {
throw new ServletException("init-param '" + ENDPOINT + "' must be specified.");
}
try {
remoteAddress = parseEndpoint(endpoint.trim());
} catch (ServletException e) {
throw e;
} catch (Exception e) {
throw new ServletException("Failed to parse an endpoint.", e);
}
try {
channelFactory = createChannelFactory(remoteAddress);
} catch (ServletException e) {
throw e;
} catch (Exception e) {
throw new ServletException("Failed to create a channel factory.", e);
}
// Stuff for testing purpose
//ServerBootstrap b = new ServerBootstrap(new DefaultLocalServerChannelFactory());
//b.getPipeline().addLast("logger", new LoggingHandler(getClass(), InternalLogLevel.INFO, true));
//b.getPipeline().addLast("handler", new EchoHandler());
//b.bind(remoteAddress);
}
protected SocketAddress parseEndpoint(String endpoint) throws Exception {
if (endpoint.startsWith("local:")) {
return new LocalAddress(endpoint.substring(6).trim());
} else {
throw new ServletException(
"Invalid or unknown endpoint: " + endpoint);
}
}
protected ChannelFactory createChannelFactory(SocketAddress remoteAddress) throws Exception {
if (remoteAddress instanceof LocalAddress) {
return new DefaultLocalClientChannelFactory();
} else {
throw new ServletException(
"Unsupported remote address type: " +
remoteAddress.getClass().getName());
}
}
@Override
public void destroy() {
try {
destroyChannelFactory(channelFactory);
} catch (Exception e) {
logger.warn("Failed to destroy a channel factory.", e);
}
}
protected void destroyChannelFactory(ChannelFactory factory) throws Exception {
factory.releaseExternalResources();
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
if (!"POST".equalsIgnoreCase(req.getMethod())) {
logger.warn("Unallowed method: " + req.getMethod());
res.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
return;
}
final ChannelPipeline pipeline = Channels.pipeline();
final ServletOutputStream out = res.getOutputStream();
final OutboundConnectionHandler handler = new OutboundConnectionHandler(out);
pipeline.addLast("handler", handler);
Channel channel = channelFactory.newChannel(pipeline);
ChannelFuture future = channel.connect(remoteAddress).awaitUninterruptibly();
if (!future.isSuccess()) {
Throwable cause = future.getCause();
logger.warn("Endpoint unavailable: " + cause.getMessage(), cause);
res.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
return;
}
ChannelFuture lastWriteFuture = null;
try {
res.setStatus(HttpServletResponse.SC_OK);
res.setHeader(HttpHeaders.Names.CONTENT_TYPE, "application/octet-stream");
res.setHeader(HttpHeaders.Names.CONTENT_TRANSFER_ENCODING, HttpHeaders.Values.BINARY);
// Initiate chunked encoding by flushing the headers.
out.flush();
PushbackInputStream in =
new PushbackInputStream(req.getInputStream());
while (channel.isConnected()) {
ChannelBuffer buffer;
try {
buffer = read(in);
} catch (EOFException e) {
break;
}
if (buffer == null) {
break;
}
lastWriteFuture = channel.write(buffer);
}
} finally {
if (lastWriteFuture == null) {
channel.close();
} else {
lastWriteFuture.addListener(ChannelFutureListener.CLOSE);
}
}
}
private static ChannelBuffer read(PushbackInputStream in) throws IOException {
byte[] buf;
int readBytes;
int bytesToRead = in.available();
if (bytesToRead > 0) {
buf = new byte[bytesToRead];
readBytes = in.read(buf);
} else if (bytesToRead == 0) {
int b = in.read();
if (b < 0 || in.available() < 0) {
return null;
}
in.unread(b);
bytesToRead = in.available();
buf = new byte[bytesToRead];
readBytes = in.read(buf);
} else {
return null;
}
assert readBytes > 0;
ChannelBuffer buffer;
if (readBytes == buf.length) {
buffer = ChannelBuffers.wrappedBuffer(buf);
} else {
// A rare case, but it sometimes happen.
buffer = ChannelBuffers.wrappedBuffer(buf, 0, readBytes);
}
return buffer;
}
private static final class OutboundConnectionHandler extends SimpleChannelUpstreamHandler {
private final ServletOutputStream out;
public OutboundConnectionHandler(ServletOutputStream out) {
this.out = out;
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
ChannelBuffer buffer = (ChannelBuffer) e.getMessage();
synchronized (this) {
buffer.readBytes(out, buffer.readableBytes());
out.flush();
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
logger.warn("Unexpected exception while HTTP tunneling", e.getCause());
e.getChannel().close();
}
}
}

View File

@ -1,347 +0,0 @@
/*
* Copyright 2009 Red Hat, Inc.
*
* Red Hat licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.http;
import java.util.Map;
import java.util.Map.Entry;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSession;
import org.jboss.netty.buffer.ChannelBufferFactory;
import org.jboss.netty.channel.ChannelConfig;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.socket.SocketChannel;
import org.jboss.netty.channel.socket.SocketChannelConfig;
import org.jboss.netty.util.internal.ConversionUtil;
/**
* The {@link ChannelConfig} of a client-side HTTP tunneling
* {@link SocketChannel}. A {@link SocketChannel} created by
* {@link HttpTunnelingClientSocketChannelFactory} will return an instance of
* this configuration type for {@link SocketChannel#getConfig()}.
*
* <h3>Available options</h3>
*
* In addition to the options provided by {@link SocketChannelConfig},
* {@link HttpTunnelingSocketChannelConfig} allows the following options in
* the option map:
*
* <table border="1" cellspacing="0" cellpadding="6">
* <tr>
* <th>Name</th><th>Associated setter method</th>
* </tr><tr>
* <td>{@code "sslContext"}</td><td>{@link #setSslContext(SSLContext)}</td>
* </tr><tr>
* <td>{@code "enabledSslCiperSuites"}</td><td>{@link #setEnabledSslCipherSuites(String[])}</td>
* </tr><tr>
* <td>{@code "enabledSslProtocols"}</td><td>{@link #setEnabledSslProtocols(String[])}</td>
* </tr><tr>
* <td>{@code "enableSslSessionCreation"}</td><td>{@link #setEnableSslSessionCreation(boolean)}</td>
* </tr>
* </table>
*
* @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
* @author Andy Taylor (andy.taylor@jboss.org)
* @author <a href="http://gleamynode.net/">Trustin Lee</a>
* @version $Rev$, $Date$
*
* @apiviz.landmark
*/
public final class HttpTunnelingSocketChannelConfig implements SocketChannelConfig {
private final HttpTunnelingClientSocketChannel channel;
private volatile String serverName;
private volatile String serverPath = "/netty-tunnel";
private volatile SSLContext sslContext;
private volatile String[] enabledSslCipherSuites;
private volatile String[] enabledSslProtocols;
private volatile boolean enableSslSessionCreation = true;
/**
* Creates a new instance.
*/
HttpTunnelingSocketChannelConfig(HttpTunnelingClientSocketChannel channel) {
this.channel = channel;
}
/**
* Returns the host name of the HTTP server. If {@code null}, the
* {@code "Host"} header is not sent by the HTTP tunneling client.
*/
public String getServerName() {
return serverName;
}
/**
* Sets the host name of the HTTP server. If {@code null}, the
* {@code "Host"} header is not sent by the HTTP tunneling client.
*/
public void setServerName(String serverName) {
this.serverName = serverName;
}
/**
* Returns the path where the {@link HttpTunnelingServlet} is mapped to.
* The default value is {@code "/netty-tunnel"}.
*/
public String getServerPath() {
return serverPath;
}
/**
* Sets the path where the {@link HttpTunnelingServlet} is mapped to.
* The default value is {@code "/netty-tunnel"}.
*/
public void setServerPath(String serverPath) {
if (serverPath == null) {
throw new NullPointerException("serverPath");
}
this.serverPath = serverPath;
}
/**
* Returns the {@link SSLContext} which is used to establish an HTTPS
* connection. If {@code null}, a plain-text HTTP connection is established.
*/
public SSLContext getSslContext() {
return sslContext;
}
/**
* Sets the {@link SSLContext} which is used to establish an HTTPS connection.
* If {@code null}, a plain-text HTTP connection is established.
*/
public void setSslContext(SSLContext sslContext) {
this.sslContext = sslContext;
}
/**
* Returns the cipher suites enabled for use on an {@link SSLEngine}.
* If {@code null}, the default value will be used.
*
* @see SSLEngine#getEnabledCipherSuites()
*/
public String[] getEnabledSslCipherSuites() {
String[] suites = enabledSslCipherSuites;
if (suites == null) {
return null;
} else {
return suites.clone();
}
}
/**
* Sets the cipher suites enabled for use on an {@link SSLEngine}.
* If {@code null}, the default value will be used.
*
* @see SSLEngine#setEnabledCipherSuites(String[])
*/
public void setEnabledSslCipherSuites(String[] suites) {
if (suites == null) {
enabledSslCipherSuites = null;
} else {
enabledSslCipherSuites = suites.clone();
}
}
/**
* Returns the protocol versions enabled for use on an {@link SSLEngine}.
*
* @see SSLEngine#getEnabledProtocols()
*/
public String[] getEnabledSslProtocols() {
String[] protocols = enabledSslProtocols;
if (protocols == null) {
return null;
} else {
return protocols.clone();
}
}
/**
* Sets the protocol versions enabled for use on an {@link SSLEngine}.
*
* @see SSLEngine#setEnabledProtocols(String[])
*/
public void setEnabledSslProtocols(String[] protocols) {
if (protocols == null) {
enabledSslProtocols = null;
} else {
enabledSslProtocols = protocols.clone();
}
}
/**
* Returns {@code true} if new {@link SSLSession}s may be established by
* an {@link SSLEngine}.
*
* @see SSLEngine#getEnableSessionCreation()
*/
public boolean isEnableSslSessionCreation() {
return enableSslSessionCreation;
}
/**
* Sets whether new {@link SSLSession}s may be established by an
* {@link SSLEngine}.
*
* @see SSLEngine#setEnableSessionCreation(boolean)
*/
public void setEnableSslSessionCreation(boolean flag) {
enableSslSessionCreation = flag;
}
@Override
public void setOptions(Map<String, Object> options) {
for (Entry<String, Object> e: options.entrySet()) {
setOption(e.getKey(), e.getValue());
}
}
@Override
public boolean setOption(String key, Object value) {
if (channel.realChannel.getConfig().setOption(key, value)) {
return true;
}
if (key.equals("serverName")){
setServerName(String.valueOf(value));
} else if (key.equals("serverPath")){
setServerPath(String.valueOf(value));
} else if (key.equals("sslContext")) {
setSslContext((SSLContext) value);
} else if (key.equals("enabledSslCipherSuites")){
setEnabledSslCipherSuites(ConversionUtil.toStringArray(value));
} else if (key.equals("enabledSslProtocols")){
setEnabledSslProtocols(ConversionUtil.toStringArray(value));
} else if (key.equals("enableSslSessionCreation")){
setEnableSslSessionCreation(ConversionUtil.toBoolean(value));
} else {
return false;
}
return true;
}
@Override
public int getReceiveBufferSize() {
return channel.realChannel.getConfig().getReceiveBufferSize();
}
@Override
public int getSendBufferSize() {
return channel.realChannel.getConfig().getSendBufferSize();
}
@Override
public int getSoLinger() {
return channel.realChannel.getConfig().getSoLinger();
}
@Override
public int getTrafficClass() {
return channel.realChannel.getConfig().getTrafficClass();
}
@Override
public boolean isKeepAlive() {
return channel.realChannel.getConfig().isKeepAlive();
}
@Override
public boolean isReuseAddress() {
return channel.realChannel.getConfig().isReuseAddress();
}
@Override
public boolean isTcpNoDelay() {
return channel.realChannel.getConfig().isTcpNoDelay();
}
@Override
public void setKeepAlive(boolean keepAlive) {
channel.realChannel.getConfig().setKeepAlive(keepAlive);
}
@Override
public void setPerformancePreferences(
int connectionTime, int latency, int bandwidth) {
channel.realChannel.getConfig().setPerformancePreferences(connectionTime, latency, bandwidth);
}
@Override
public void setReceiveBufferSize(int receiveBufferSize) {
channel.realChannel.getConfig().setReceiveBufferSize(receiveBufferSize);
}
@Override
public void setReuseAddress(boolean reuseAddress) {
channel.realChannel.getConfig().setReuseAddress(reuseAddress);
}
@Override
public void setSendBufferSize(int sendBufferSize) {
channel.realChannel.getConfig().setSendBufferSize(sendBufferSize);
}
@Override
public void setSoLinger(int soLinger) {
channel.realChannel.getConfig().setSoLinger(soLinger);
}
@Override
public void setTcpNoDelay(boolean tcpNoDelay) {
channel.realChannel.getConfig().setTcpNoDelay(tcpNoDelay);
}
@Override
public void setTrafficClass(int trafficClass) {
channel.realChannel.getConfig().setTrafficClass(trafficClass);
}
@Override
public ChannelBufferFactory getBufferFactory() {
return channel.realChannel.getConfig().getBufferFactory();
}
@Override
public int getConnectTimeoutMillis() {
return channel.realChannel.getConfig().getConnectTimeoutMillis();
}
@Override
public ChannelPipelineFactory getPipelineFactory() {
return channel.realChannel.getConfig().getPipelineFactory();
}
@Override
public void setBufferFactory(ChannelBufferFactory bufferFactory) {
channel.realChannel.getConfig().setBufferFactory(bufferFactory);
}
@Override
public void setConnectTimeoutMillis(int connectTimeoutMillis) {
channel.realChannel.getConfig().setConnectTimeoutMillis(connectTimeoutMillis);
}
@Override
public void setPipelineFactory(ChannelPipelineFactory pipelineFactory) {
channel.realChannel.getConfig().setPipelineFactory(pipelineFactory);
}
}

View File

@ -13,11 +13,11 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import static org.jboss.netty.channel.socket.httptunnel.SaturationStateChange.DESATURATED;
import static org.jboss.netty.channel.socket.httptunnel.SaturationStateChange.NO_CHANGE;
import static org.jboss.netty.channel.socket.httptunnel.SaturationStateChange.SATURATED;
import static org.jboss.netty.channel.socket.http.SaturationStateChange.DESATURATED;
import static org.jboss.netty.channel.socket.http.SaturationStateChange.NO_CHANGE;
import static org.jboss.netty.channel.socket.http.SaturationStateChange.SATURATED;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
/**
* Represents the state change of a chanel in response in the amount of pending data to be

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.net.InetSocketAddress;
import java.util.List;

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.ChannelFuture;

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.net.InetSocketAddress;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
/**
* This interface is used by the server end of an http tunnel to generate new

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.net.SocketAddress;

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.util.List;

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.util.ArrayList;
import java.util.List;

View File

@ -1,122 +0,0 @@
/*
* Copyright 2009 Red Hat, Inc.
*
* Red Hat licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.http.tunnel;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.URI;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.http.HttpTunnelingClientSocketChannelFactory;
import org.jboss.netty.channel.socket.oio.OioClientSocketChannelFactory;
import org.jboss.netty.example.securechat.SecureChatSslContextFactory;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;
import org.jboss.netty.handler.logging.LoggingHandler;
import org.jboss.netty.logging.InternalLogLevel;
/**
* An HTTP tunneled version of the telnet client example. Please refer to the
* API documentation of the <tt>org.jboss.netty.channel.socket.http</tt> package
* for the detailed instruction on how to deploy the server-side HTTP tunnel in
* your Servlet container.
*
* @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
* @author Andy Taylor (andy.taylor@jboss.org)
* @version $Rev$, $Date$
*/
public class HttpTunnelingClientExample {
public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.err.println(
"Usage: " + HttpTunnelingClientExample.class.getSimpleName() +
" <URL>");
System.err.println(
"Example: " + HttpTunnelingClientExample.class.getSimpleName() +
" http://localhost:8080/netty-tunnel");
return;
}
URI uri = new URI(args[0]);
String scheme = uri.getScheme() == null? "http" : uri.getScheme();
// Configure the client.
ClientBootstrap b = new ClientBootstrap(
new HttpTunnelingClientSocketChannelFactory(
new OioClientSocketChannelFactory(Executors.newCachedThreadPool())));
b.setPipelineFactory(new ChannelPipelineFactory() {
@Override
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(
new StringDecoder(),
new StringEncoder(),
new LoggingHandler(InternalLogLevel.INFO));
}
});
// Set additional options required by the HTTP tunneling transport.
b.setOption("serverName", uri.getHost());
b.setOption("serverPath", uri.getRawPath());
// Configure SSL if necessary
if (scheme.equals("https")) {
b.setOption("sslContext", SecureChatSslContextFactory.getClientContext());
} else if (!scheme.equals("http")) {
// Only HTTP and HTTPS are supported.
System.err.println("Only HTTP(S) is supported.");
return;
}
// Make the connection attempt.
ChannelFuture channelFuture = b.connect(
new InetSocketAddress(uri.getHost(), uri.getPort()));
channelFuture.awaitUninterruptibly();
// Read commands from the stdin.
System.out.println("Enter text ('quit' to exit)");
ChannelFuture lastWriteFuture = null;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
for (; ;) {
String line = in.readLine();
if (line == null || "quit".equalsIgnoreCase(line)) {
break;
}
// Sends the received line to the server.
lastWriteFuture = channelFuture.getChannel().write(line);
}
// Wait until all messages are flushed before closing the channel.
if (lastWriteFuture != null) {
lastWriteFuture.awaitUninterruptibly();
}
channelFuture.getChannel().close();
// Wait until the connection is closed or the connection attempt fails.
channelFuture.getChannel().getCloseFuture().awaitUninterruptibly();
// Shut down all threads.
b.releaseExternalResources();
}
}

View File

@ -1,54 +0,0 @@
/*
* Copyright 2009 Red Hat, Inc.
*
* Red Hat licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.http.tunnel;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.local.DefaultLocalServerChannelFactory;
import org.jboss.netty.channel.local.LocalAddress;
import org.jboss.netty.example.echo.EchoServerHandler;
/**
* Deploy this in JBossAS 5 or other IoC container by adding the following bean.
*
* <pre>
* &lt;bean name="org.jboss.netty.example.http.tunnel.LocalEchoServerRegistration"
* class="org.jboss.netty.example.http.tunnel.LocalEchoServerRegistration" /&gt;
* </pre>
*
* @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
* @author Andy Taylor (andy.taylor@jboss.org)
* @version $Rev$, $Date$
*/
public class LocalEchoServerRegistration {
private final ChannelFactory factory = new DefaultLocalServerChannelFactory();
private volatile Channel serverChannel;
public void start() {
ServerBootstrap serverBootstrap = new ServerBootstrap(factory);
EchoServerHandler handler = new EchoServerHandler();
serverBootstrap.getPipeline().addLast("handler", handler);
// Note that "myLocalServer" is the endpoint which was specified in web.xml.
serverChannel = serverBootstrap.bind(new LocalAddress("myLocalServer"));
}
public void stop() {
serverChannel.close();
}
}

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.util.Map;
import java.util.Map.Entry;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.util.LinkedList;
import java.util.Queue;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.util.ArrayList;
import java.util.List;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import static org.jboss.netty.channel.Channels.fireChannelBound;
import static org.jboss.netty.channel.Channels.fireChannelConnected;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import org.jboss.netty.buffer.ChannelBufferFactory;
import org.jboss.netty.buffer.HeapChannelBufferFactory;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.net.InetSocketAddress;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import static org.junit.Assert.assertEquals;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.net.InetAddress;
import java.net.InetSocketAddress;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.net.InetSocketAddress;
import java.util.ArrayList;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import static org.junit.Assert.assertTrue;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import org.jboss.netty.channel.ChannelDownstreamHandler;
import org.jboss.netty.channel.ChannelEvent;

View File

@ -1,7 +1,7 @@
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import static org.junit.Assert.*;
import static org.jboss.netty.channel.socket.httptunnel.SaturationStateChange.*;
import static org.jboss.netty.channel.socket.http.SaturationStateChange.*;
import org.junit.Before;
import org.junit.Test;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import static org.junit.Assert.assertEquals;
@ -24,7 +24,7 @@ import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.httptunnel.ServerMessageSwitchUpstreamInterface.TunnelStatus;
import org.jboss.netty.channel.socket.http.ServerMessageSwitchUpstreamInterface.TunnelStatus;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jmock.Expectations;
import org.jmock.integration.junit4.JMock;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import java.util.LinkedList;
import java.util.Queue;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;

View File

@ -14,7 +14,7 @@
* under the License.
*/
package org.jboss.netty.channel.socket.httptunnel;
package org.jboss.netty.channel.socket.http;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;