package org.wildfly.swarm.monitor.runtime;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.util.LinkedList;
import java.util.List;
import io.undertow.UndertowLogger;
import io.undertow.UndertowMessages;
import io.undertow.conduits.EmptyStreamSourceConduit;
import io.undertow.connector.ByteBufferPool;
import io.undertow.server.DefaultByteBufferPool;
import io.undertow.server.HttpServerExchange;
import io.undertow.server.HttpUpgradeListener;
import io.undertow.server.SSLSessionInfo;
import io.undertow.server.ServerConnection;
import io.undertow.server.XnioBufferPoolAdaptor;
import io.undertow.util.PooledAdaptor;
import org.jboss.logging.Logger;
import org.xnio.ChannelListener;
import org.xnio.Option;
import org.xnio.OptionMap;
import org.xnio.Pool;
import org.xnio.StreamConnection;
import org.xnio.XnioIoThread;
import org.xnio.XnioWorker;
import org.xnio.channels.Configurable;
import org.xnio.channels.ConnectedChannel;
import org.xnio.conduits.BufferedStreamSinkConduit;
import org.xnio.conduits.ConduitStreamSinkChannel;
import org.xnio.conduits.ConduitStreamSourceChannel;
import org.xnio.conduits.NullStreamSinkConduit;
import org.xnio.conduits.StreamSinkConduit;
/**
* An Undertow in vm http connection
*
* @author Heiko Braun
*/
final class InVMConnection extends ServerConnection {
private static Logger LOG = Logger.getLogger(InVMConnection.class);
private final ByteBufferPool bufferPool;
private final XnioWorker worker;
private SSLSessionInfo sslSessionInfo;
private XnioBufferPoolAdaptor poolAdaptor;
private BufferingSinkConduit bufferSink;
protected final List<CloseListener> closeListeners = new LinkedList<>();
InVMConnection(XnioWorker worker, int port) {
this.bufferPool = new DefaultByteBufferPool(false, 1024, 0, 0);
this.worker = worker;
this.address = new InetSocketAddress(port); // port carried forward from the initial
}
public void flushTo(StringBuffer sb) {
bufferSink.flushTo(sb);
}
@SuppressWarnings("deprecation")
@Override
public Pool<ByteBuffer> getBufferPool() {
if (poolAdaptor == null) {
poolAdaptor = new XnioBufferPoolAdaptor(getByteBufferPool());
}
return poolAdaptor;
}
@Override
public ByteBufferPool getByteBufferPool() {
return bufferPool;
}
@Override
public XnioWorker getWorker() {
return null;
}
@Override
public XnioIoThread getIoThread() {
return null;
}
@Override
public HttpServerExchange sendOutOfBandResponse(HttpServerExchange exchange) {
throw UndertowMessages.MESSAGES.outOfBandResponseNotSupported();
}
@Override
public boolean isContinueResponseSupported() {
return false;
}
@Override
public void terminateRequestChannel(HttpServerExchange exchange) {
LOG.trace("Terminate Mock exchange");
}
@Override
public boolean isOpen() {
return !this.closed;
}
@Override
public boolean supportsOption(Option<?> option) {
return false;
}
@Override
public <T> T getOption(Option<T> option) throws IOException {
return null;
}
@Override
public <T> T setOption(Option<T> option, T value) throws IllegalArgumentException, IOException {
return null;
}
@Override
public void close() throws IOException {
this.closed = true;
}
@Override
public SocketAddress getPeerAddress() {
return null;
}
@Override
public <A extends SocketAddress> A getPeerAddress(Class<A> type) {
return null;
}
@Override
public ChannelListener.Setter<? extends ConnectedChannel> getCloseSetter() {
return null;
}
@Override
public SocketAddress getLocalAddress() {
return address;
}
@Override
public <A extends SocketAddress> A getLocalAddress(Class<A> type) {
return (A) address;
}
@Override
public OptionMap getUndertowOptions() {
return OptionMap.EMPTY;
}
@Override
public int getBufferSize() {
return 1024;
}
@Override
public SSLSessionInfo getSslSessionInfo() {
return sslSessionInfo;
}
@Override
public void setSslSessionInfo(SSLSessionInfo sessionInfo) {
sslSessionInfo = sessionInfo;
}
@Override
public void addCloseListener(CloseListener listener) {
this.closeListeners.add(listener);
}
@Override
public StreamConnection upgradeChannel() {
return null;
}
@Override
public ConduitStreamSinkChannel getSinkChannel() {
ConduitStreamSinkChannel sinkChannel = new ConduitStreamSinkChannel(
Configurable.EMPTY,
new BufferedStreamSinkConduit(
new NullStreamSinkConduit(worker.getIoThread()),
new PooledAdaptor(bufferPool.allocate())
)
);
sinkChannel.setCloseListener(conduitStreamSinkChannel -> {
for (CloseListener l : closeListeners) {
try {
l.closed(InVMConnection.this);
} catch (Throwable e) {
UndertowLogger.REQUEST_LOGGER.exceptionInvokingCloseListener(l, e);
}
}
});
return sinkChannel;
}
@Override
public ConduitStreamSourceChannel getSourceChannel() {
return new ConduitStreamSourceChannel(Configurable.EMPTY, new EmptyStreamSourceConduit(worker.getIoThread()));
}
@Override
protected StreamSinkConduit getSinkConduit(HttpServerExchange exchange, StreamSinkConduit conduit) {
bufferSink = new BufferingSinkConduit(conduit);
return bufferSink;
}
@Override
protected boolean isUpgradeSupported() {
return false;
}
@Override
protected boolean isConnectSupported() {
return false;
}
@Override
protected void exchangeComplete(HttpServerExchange exchange) {
LOG.trace("InVM exchange complete");
}
@Override
protected void setUpgradeListener(HttpUpgradeListener upgradeListener) {
//ignore
}
@Override
protected void setConnectListener(HttpUpgradeListener connectListener) {
//ignore
}
@Override
protected void maxEntitySizeUpdated(HttpServerExchange exchange) {
}
@Override
public String getTransportProtocol() {
return "mock";
}
private boolean closed;
private final InetSocketAddress address;
}