private void handleConnected(final StreamConnection connection, final ClientCallback<ClientConnection> listener, final ByteBufferPool bufferPool, final OptionMap options, URI uri) { boolean h2 = options.get(UndertowOptions.ENABLE_HTTP2, false); if(connection instanceof SslConnection && (h2)) { List<ALPNClientSelector.ALPNProtocol> protocolList = new ArrayList<>(); if(h2) { protocolList.add(Http2ClientProvider.alpnProtocol(listener, uri, bufferPool, options)); } ALPNClientSelector.runAlpn((SslConnection) connection, new ChannelListener<SslConnection>() { @Override public void handleEvent(SslConnection connection) { listener.completed(new HttpClientConnection(connection, options, bufferPool)); } }, listener, protocolList.toArray(new ALPNClientSelector.ALPNProtocol[protocolList.size()])); } else { if(connection instanceof SslConnection) { try { ((SslConnection) connection).startHandshake(); } catch (Throwable t) { listener.failed((t instanceof IOException) ? (IOException) t : new IOException(t)); } } listener.completed(new HttpClientConnection(connection, options, bufferPool)); } } }
public void requestDataSent() { if(http2UpgradeReceived) { doHttp2Upgrade(); } }
void terminateRequest() { if(anyAreSet(state, REQUEST_TERMINATED)) { return; } log.debugf("request terminated for request to %s %s", clientConnection.getPeerAddress(), getRequest().getPath()); state |= REQUEST_TERMINATED; clientConnection.requestDataSent(); if (anyAreSet(state, RESPONSE_TERMINATED)) { clientConnection.exchangeDone(); } }
void terminateResponse() { if(anyAreSet(state, RESPONSE_TERMINATED)) { return; } log.debugf("response terminated for request to %s %s", clientConnection.getPeerAddress(), getRequest().getPath()); state |= RESPONSE_TERMINATED; if (anyAreSet(state, REQUEST_TERMINATED)) { clientConnection.exchangeDone(); } }
log.debugf("exchange complete in connection to %s", getPeerAddress()); connection.getSourceChannel().resumeReads(); } else { initiateRequest(next);
private void handleError(Throwable exception) { if (exception instanceof IOException) { handleError((IOException) exception); } else { handleError(new IOException(exception)); } } private void handleError(IOException exception) {
public void close() throws IOException { log.debugf("close called on connection to %s", getPeerAddress()); if(http2Delegate != null) { http2Delegate.close(); } if (anyAreSet(state, CLOSED)) { return; } state |= CLOSED | CLOSE_REQ; ConnectionUtils.cleanClose(connection); }
@Override public StreamSourceChannel getResponseChannel() { return new DetachableStreamSourceChannel(clientConnection.getConnection().getSourceChannel()) { @Override protected boolean isFinished() { return anyAreSet(state, RESPONSE_TERMINATED); } }; }
protected void doHttp2Upgrade() { try { StreamConnection connectedStreamChannel = this.performUpgrade(); Http2Channel http2Channel = new Http2Channel(connectedStreamChannel, null, bufferPool, null, true, true, options); Http2ClientConnection http2ClientConnection = new Http2ClientConnection(http2Channel, currentRequest.getResponseCallback(), currentRequest.getRequest(), currentRequest.getRequest().getRequestHeaders().getFirst(Headers.HOST), clientStatistics, false); http2ClientConnection.getCloseSetter().set(new ChannelListener<ClientConnection>() { @Override public void handleEvent(ClientConnection channel) { ChannelListeners.invokeChannelListener(HttpClientConnection.this, HttpClientConnection.this.closeSetter.get()); } }); http2Delegate = http2ClientConnection; connectedStreamChannel.getSourceChannel().wakeupReads(); //make sure the read listener is immediately invoked, as it may not happen if data is pushed back currentRequest = null; pendingResponse = null; } catch (IOException e) { UndertowLogger.REQUEST_IO_LOGGER.ioException(e); safeClose(this); } }
@Override public void sendRequest(final ClientRequest request, final ClientCallback<ClientExchange> clientCallback) { if(http2Delegate != null) { http2Delegate.sendRequest(request, clientCallback); return; } if (anyAreSet(state, UPGRADE_REQUESTED | UPGRADED | CLOSE_REQ | CLOSED)) { clientCallback.failed(UndertowClientMessages.MESSAGES.invalidConnectionState()); return; } final HttpClientExchange httpClientExchange = new HttpClientExchange(clientCallback, request, this); boolean ssl = this.connection instanceof SslConnection; if(!ssl && !http2Tried && options.get(UndertowOptions.ENABLE_HTTP2, false) && !request.getRequestHeaders().contains(Headers.UPGRADE)) { //this is the first request, as we want to try a HTTP2 upgrade request.getRequestHeaders().put(new HttpString("HTTP2-Settings"), Http2ClearClientProvider.createSettingsFrame(options, bufferPool)); request.getRequestHeaders().put(Headers.UPGRADE, Http2Channel.CLEARTEXT_UPGRADE_STRING); request.getRequestHeaders().put(Headers.CONNECTION, "Upgrade, HTTP2-Settings"); http2Tried = true; } if (currentRequest == null) { initiateRequest(httpClientExchange); } else { pendingQueue.add(httpClientExchange); } }
void terminateResponse() { if(anyAreSet(state, RESPONSE_TERMINATED)) { return; } log.debugf("response terminated for request to %s %s", clientConnection.getPeerAddress(), getRequest().getPath()); state |= RESPONSE_TERMINATED; if (anyAreSet(state, REQUEST_TERMINATED)) { clientConnection.exchangeDone(); } }
log.debugf("exchange complete in connection to %s", getPeerAddress()); connection.getSourceChannel().resumeReads(); } else { initiateRequest(next);
hasContent = length != 0; } catch (NumberFormatException e) { handleError(e); return; handleError(UndertowClientMessages.MESSAGES.unknownTransferEncoding(transferEncodingString)); return; handleError(t);
public void handleEvent(StreamConnection channel) { log.debugf("connection to %s closed", getPeerAddress()); HttpClientConnection.this.state |= CLOSED; ChannelListeners.invokeChannelListener(HttpClientConnection.this, closeSetter.get()); try { if (pooledBuffer != null) { pooledBuffer.close(); } } catch (Throwable ignored){} for(ChannelListener<ClientConnection> listener : closeListeners) { listener.handleEvent(HttpClientConnection.this); } HttpClientExchange pending = pendingQueue.poll(); while (pending != null) { pending.setFailed(new ClosedChannelException()); pending = pendingQueue.poll(); } if(currentRequest != null) { currentRequest.setFailed(new ClosedChannelException()); currentRequest = null; pendingResponse = null; } } });
@Override public StreamSinkChannel getRequestChannel() { return new DetachableStreamSinkChannel(clientConnection.getConnection().getSinkChannel()) { @Override protected boolean isFinished() { return anyAreSet(state, REQUEST_TERMINATED); } }; }
protected void doHttp2Upgrade() { try { StreamConnection connectedStreamChannel = this.performUpgrade(); Http2Channel http2Channel = new Http2Channel(connectedStreamChannel, null, bufferPool, null, true, true, options); Http2ClientConnection http2ClientConnection = new Http2ClientConnection(http2Channel, currentRequest.getResponseCallback(), currentRequest.getRequest(), currentRequest.getRequest().getRequestHeaders().getFirst(Headers.HOST), clientStatistics, false); http2ClientConnection.getCloseSetter().set(new ChannelListener<ClientConnection>() { @Override public void handleEvent(ClientConnection channel) { ChannelListeners.invokeChannelListener(HttpClientConnection.this, HttpClientConnection.this.closeSetter.get()); } }); http2Delegate = http2ClientConnection; connectedStreamChannel.getSourceChannel().wakeupReads(); //make sure the read listener is immediately invoked, as it may not happen if data is pushed back currentRequest = null; pendingResponse = null; } catch (IOException e) { UndertowLogger.REQUEST_IO_LOGGER.ioException(e); safeClose(this); } }
@Override public void sendRequest(final ClientRequest request, final ClientCallback<ClientExchange> clientCallback) { if(http2Delegate != null) { http2Delegate.sendRequest(request, clientCallback); return; } if (anyAreSet(state, UPGRADE_REQUESTED | UPGRADED | CLOSE_REQ | CLOSED)) { clientCallback.failed(UndertowClientMessages.MESSAGES.invalidConnectionState()); return; } final HttpClientExchange httpClientExchange = new HttpClientExchange(clientCallback, request, this); boolean ssl = this.connection instanceof SslConnection; if(!ssl && !http2Tried && options.get(UndertowOptions.ENABLE_HTTP2, false) && !request.getRequestHeaders().contains(Headers.UPGRADE)) { //this is the first request, as we want to try a HTTP2 upgrade request.getRequestHeaders().put(new HttpString("HTTP2-Settings"), Http2ClearClientProvider.createSettingsFrame(options, bufferPool)); request.getRequestHeaders().put(Headers.UPGRADE, Http2Channel.CLEARTEXT_UPGRADE_STRING); request.getRequestHeaders().put(Headers.CONNECTION, "Upgrade, HTTP2-Settings"); http2Tried = true; } if (currentRequest == null) { initiateRequest(httpClientExchange); } else { pendingQueue.add(httpClientExchange); } }
void terminateRequest() { if(anyAreSet(state, REQUEST_TERMINATED)) { return; } log.debugf("request terminated for request to %s %s", clientConnection.getPeerAddress(), getRequest().getPath()); state |= REQUEST_TERMINATED; clientConnection.requestDataSent(); if (anyAreSet(state, RESPONSE_TERMINATED)) { clientConnection.exchangeDone(); } }
void terminateResponse() { if(anyAreSet(state, RESPONSE_TERMINATED)) { return; } log.debugf("response terminated for request to %s %s", clientConnection.getPeerAddress(), getRequest().getPath()); state |= RESPONSE_TERMINATED; if (anyAreSet(state, REQUEST_TERMINATED)) { clientConnection.exchangeDone(); } }
log.debugf("exchange complete in connection to %s", getPeerAddress()); connection.getSourceChannel().resumeReads(); } else { initiateRequest(next);