@Override public int read(final byte[] b, final int off, final int len) throws IOException { if (anyAreSet(state, FLAG_CLOSED)) { throw UndertowServletMessages.MESSAGES.streamIsClosed(); } if (anyAreSet(state, FLAG_FINISHED)) { return -1; } ByteBuffer buffer = ByteBuffer.wrap(b, off, len); if (listener == null) { int res = Channels.readBlocking(channel, buffer); if (res == -1) { state |= FLAG_FINISHED; } return res; } else { if (anyAreClear(state, FLAG_READY)) { throw UndertowServletMessages.MESSAGES.streamNotReady(); } int res = channel.read(buffer); if (res == -1) { state |= FLAG_FINISHED; } else if (res == 0) { state &= ~FLAG_READY; channel.resumeReads(); } return res; } }
@Override public void handleEvent(StreamSourceChannel channel) { if (this.subscriptionClosed) { return; } try { ByteBuffer buffer = this.pooledBuffer.getBuffer(); int count; do { count = channel.read(buffer); if (count == 0) { return; } else if (count == -1) { if (buffer.position() > 0) { doOnNext(buffer); } doOnComplete(); } else { if (buffer.remaining() == 0) { if (this.demand == 0) { channel.suspendReads(); } doOnNext(buffer); if (this.demand > 0) { scheduleNextMessage(); } break; } } } while (count > 0); } catch (IOException e) { doOnError(e); } }
@Override public void handleEvent(StreamSourceChannel channel) { if (this.session.isDisconnected()) { if (logger.isDebugEnabled()) { logger.debug("SockJS sockJsSession closed, closing response."); } IoUtils.safeClose(this.connection); throw new SockJsException("Session closed.", this.session.getId(), null); } Object pooled = undertowBufferSupport.allocatePooledResource(); try { int r; do { ByteBuffer buffer = undertowBufferSupport.getByteBuffer(pooled); buffer.clear(); r = channel.read(buffer); buffer.flip(); if (r == 0) { return; } else if (r == -1) { onSuccess(); } else { while (buffer.hasRemaining()) { int b = buffer.get(); if (b == '\n') { handleFrame(); } else { this.outputStream.write(b); } } } } while (r > 0); } catch (IOException exc) { onFailure(exc); } finally { undertowBufferSupport.closePooledResource(pooled); } }
public void handleEvent(final StreamSourceChannel channel) { Pooled<ByteBuffer> existing = connection.getExtraBytes(); final Pooled<ByteBuffer> pooled = existing == null ? connection.getBufferPool().allocate() : existing; final ByteBuffer buffer = pooled.getResource(); boolean free = true; try { int res; do { if (existing == null) { buffer.clear(); try { res = channel.read(buffer); } catch (IOException e) { UndertowLogger.REQUEST_IO_LOGGER.debug("Error reading request", e); IoUtils.safeClose(connection); return; } } else { res = buffer.remaining(); } if (res == 0) { if (!channel.isReadResumed()) { channel.getReadSetter().set(this); channel.resumeReads(); } return; } else if (res == -1) { try { channel.suspendReads(); channel.shutdownReads(); final StreamSinkChannel responseChannel = this.connection.getChannel().getSinkChannel(); responseChannel.shutdownWrites(); // will return false if there's a response queued ahead of this one, so we'll set up a // listener then if (!responseChannel.flush()) { responseChannel .getWriteSetter() .set(ChannelListeners.flushingChannelListener(null, null)); responseChannel.resumeWrites(); } } catch (IOException e) { UndertowLogger.REQUEST_IO_LOGGER.debug("Error reading request", e); // f**k it, it's all ruined IoUtils.safeClose(channel); return; } return; } if (existing != null) { existing = null; connection.setExtraBytes(null); } else { buffer.flip(); } parser.handle(buffer, state, httpServerExchange); if (buffer.hasRemaining()) { free = false; connection.setExtraBytes(pooled); } int total = read + res; read = total; if (read > maxRequestSize) { UndertowLogger.REQUEST_LOGGER.requestHeaderWasTooLarge( connection.getPeerAddress(), maxRequestSize); IoUtils.safeClose(connection); return; } } while (!state.isComplete()); // we remove ourselves as the read listener from the channel; // if the http handler doesn't set any then reads will suspend, which is the right thing to do channel.getReadSetter().set(null); channel.suspendReads(); final HttpServerExchange httpServerExchange = this.httpServerExchange; httpServerExchange.putAttachment( UndertowOptions.ATTACHMENT_KEY, connection.getUndertowOptions()); httpServerExchange.setRequestScheme(connection.getSslSession() != null ? "https" : "http"); this.httpServerExchange = null; HttpTransferEncoding.setupRequest(httpServerExchange); HttpHandlers.executeRootHandler( connection.getRootHandler(), httpServerExchange, Thread.currentThread() instanceof XnioExecutor); } catch (Exception e) { sendBadRequestAndClose(connection.getChannel(), e); return; } finally { if (free) pooled.free(); } }
private void doParse(final StreamSourceChannel channel) throws IOException { int c = 0; final Pooled<ByteBuffer> pooled = exchange.getConnection().getBufferPool().allocate(); try { final ByteBuffer buffer = pooled.getResource(); do { buffer.clear(); c = channel.read(buffer); if (c > 0) { buffer.flip(); while (buffer.hasRemaining()) { byte n = buffer.get(); switch (state) { case 0: { if (n == '=') { name = builder.toString(); builder.setLength(0); state = 2; } else if (n == '&') { data.add(builder.toString(), ""); builder.setLength(0); state = 0; } else if (n == '%' || n == '+') { state = 1; builder.append((char) n); } else { builder.append((char) n); } break; } case 1: { if (n == '=') { name = URLDecoder.decode(builder.toString(), charset); builder.setLength(0); state = 2; } else if (n == '&') { data.add(URLDecoder.decode(builder.toString(), charset), ""); builder.setLength(0); state = 0; } else { builder.append((char) n); } break; } case 2: { if (n == '&') { data.add(name, builder.toString()); builder.setLength(0); state = 0; } else if (n == '%' || n == '+') { state = 3; builder.append((char) n); } else { builder.append((char) n); } break; } case 3: { if (n == '&') { data.add(name, URLDecoder.decode(builder.toString(), charset)); builder.setLength(0); state = 0; } else { builder.append((char) n); } break; } } } } } while (c > 0); if (c == -1) { if (state == 2) { data.add(name, builder.toString()); } else if (state == 3) { data.add(name, URLDecoder.decode(builder.toString(), charset)); } else if (builder.length() > 0) { if (state == 1) { data.add(URLDecoder.decode(builder.toString(), charset), ""); } else { data.add(builder.toString(), ""); } } state = 4; exchange.putAttachment(FORM_DATA, data); } } finally { pooled.free(); } }
public void handleEvent(StreamSourceChannel channel) { HttpResponseBuilder builder = pendingResponse; final Pooled<ByteBuffer> pooled = bufferPool.allocate(); final ByteBuffer buffer = pooled.getResource(); boolean free = true; try { if (builder == null) { // read ready when no request pending buffer.clear(); try { int res = channel.read(buffer); if (res == -1) { UndertowLogger.CLIENT_LOGGER.debugf( "Connection to %s was closed by the target server", connection.getPeerAddress()); IoUtils.safeClose(HttpClientConnection.this); } else if (res != 0) { UndertowLogger.CLIENT_LOGGER.debugf( "Target server %s sent unexpected data when no request pending, closing connection", connection.getPeerAddress()); IoUtils.safeClose(HttpClientConnection.this); } // otherwise it is a spurious notification } catch (IOException e) { if (UndertowLogger.CLIENT_LOGGER.isDebugEnabled()) { UndertowLogger.CLIENT_LOGGER.debugf(e, "Connection closed with IOException"); } safeClose(connection); } return; } final ResponseParseState state = builder.getParseState(); int res; do { buffer.clear(); try { res = channel.read(buffer); } catch (IOException e) { if (UndertowLogger.CLIENT_LOGGER.isDebugEnabled()) { UndertowLogger.CLIENT_LOGGER.debugf(e, "Connection closed with IOException"); } safeClose(channel); return; } if (res == 0) { if (!channel.isReadResumed()) { channel.getReadSetter().set(this); channel.resumeReads(); } return; } else if (res == -1) { channel.suspendReads(); IoUtils.safeClose(HttpClientConnection.this); try { final StreamSinkChannel requestChannel = connection.getSinkChannel(); requestChannel.shutdownWrites(); // will return false if there's a response queued ahead of this one, so we'll set up a // listener then if (!requestChannel.flush()) { requestChannel .getWriteSetter() .set(ChannelListeners.flushingChannelListener(null, null)); requestChannel.resumeWrites(); } // Cancel the current active request currentRequest.setFailed(new IOException(MESSAGES.connectionClosed())); } catch (IOException e) { if (UndertowLogger.CLIENT_LOGGER.isDebugEnabled()) { UndertowLogger.CLIENT_LOGGER.debugf( e, "Connection closed with IOException when attempting to shut down reads"); } IoUtils.safeClose(channel); // Cancel the current active request currentRequest.setFailed(e); return; } return; } buffer.flip(); HttpResponseParser.INSTANCE.handle(buffer, state, builder); if (buffer.hasRemaining()) { free = false; pushBackStreamSourceConduit.pushBack(pooled); } } while (!state.isComplete()); final ClientResponse response = builder.build(); String connectionString = response.getResponseHeaders().getFirst(CONNECTION); // check if an upgrade worked if (anyAreSet(HttpClientConnection.this.state, UPGRADE_REQUESTED)) { if ((connectionString == null || !UPGRADE.equalToString(connectionString)) && !response.getResponseHeaders().contains(UPGRADE)) { // just unset the upgrade requested flag HttpClientConnection.this.state &= ~UPGRADE_REQUESTED; } } if (connectionString != null) { if (HttpString.tryFromString(connectionString).equals(Headers.CLOSE)) { HttpClientConnection.this.state |= CLOSE_REQ; } } if (builder.getStatusCode() == 100) { pendingResponse = new HttpResponseBuilder(); currentRequest.setContinueResponse(response); } else { prepareResponseChannel(response, currentRequest); channel.getReadSetter().set(null); channel.suspendReads(); pendingResponse = null; currentRequest.setResponse(response); } } catch (Exception e) { UndertowLogger.CLIENT_LOGGER.exceptionProcessingRequest(e); IoUtils.safeClose(connection); currentRequest.setFailed(new IOException(e)); } finally { if (free) pooled.free(); } }