use of org.xnio.conduits.PushBackStreamSourceConduit in project undertow by undertow-io.
the class ALPNClientSelector method runAlpn.
public static void runAlpn(final SslConnection sslConnection, final ChannelListener<SslConnection> fallback, final ClientCallback<ClientConnection> failedListener, final ALPNProtocol... details) {
SslConduit conduit = UndertowXnioSsl.getSslConduit(sslConnection);
final ALPNProvider provider = ALPNManager.INSTANCE.getProvider(conduit.getSSLEngine());
if (provider == null) {
fallback.handleEvent(sslConnection);
return;
}
String[] protocols = new String[details.length];
final Map<String, ALPNProtocol> protocolMap = new HashMap<>();
for (int i = 0; i < protocols.length; ++i) {
protocols[i] = details[i].getProtocol();
protocolMap.put(details[i].getProtocol(), details[i]);
}
final SSLEngine sslEngine = provider.setProtocols(conduit.getSSLEngine(), protocols);
conduit.setSslEngine(sslEngine);
final AtomicReference<Boolean> handshakeDone = new AtomicReference<>(false);
try {
sslConnection.startHandshake();
sslConnection.getHandshakeSetter().set(new ChannelListener<SslConnection>() {
@Override
public void handleEvent(SslConnection channel) {
if (handshakeDone.get()) {
return;
}
handshakeDone.set(true);
}
});
sslConnection.getSourceChannel().getReadSetter().set(new ChannelListener<StreamSourceChannel>() {
@Override
public void handleEvent(StreamSourceChannel channel) {
String selectedProtocol = provider.getSelectedProtocol(sslEngine);
if (selectedProtocol != null) {
handleSelected(selectedProtocol);
} else {
ByteBuffer buf = ByteBuffer.allocate(100);
try {
int read = channel.read(buf);
if (read > 0) {
buf.flip();
PushBackStreamSourceConduit pb = new PushBackStreamSourceConduit(sslConnection.getSourceChannel().getConduit());
pb.pushBack(new ImmediatePooled<>(buf));
sslConnection.getSourceChannel().setConduit(pb);
} else if (read == -1) {
failedListener.failed(new ClosedChannelException());
}
selectedProtocol = provider.getSelectedProtocol(sslEngine);
if (selectedProtocol != null) {
handleSelected(selectedProtocol);
} else if (read > 0 || handshakeDone.get()) {
sslConnection.getSourceChannel().suspendReads();
fallback.handleEvent(sslConnection);
return;
}
} catch (IOException e) {
failedListener.failed(e);
}
}
}
private void handleSelected(String selected) {
if (selected.isEmpty()) {
sslConnection.getSourceChannel().suspendReads();
fallback.handleEvent(sslConnection);
return;
} else {
ALPNClientSelector.ALPNProtocol details = protocolMap.get(selected);
if (details == null) {
//should never happen
sslConnection.getSourceChannel().suspendReads();
fallback.handleEvent(sslConnection);
return;
} else {
sslConnection.getSourceChannel().suspendReads();
details.getSelected().handleEvent(sslConnection);
}
}
}
});
sslConnection.getSourceChannel().resumeReads();
} catch (IOException e) {
failedListener.failed(e);
} catch (Throwable e) {
failedListener.failed(new IOException(e));
}
}
Aggregations