code: private void doRead() {
          if (context == null) {
              context = vertx.getOrCreateContext();
          }
          if (state == STATUS_ACTIVE) {
              final Handler<Buffer> dataHandler = this.dataHandler;
              final Handler<Void> closeHandler = this.closeHandler;
              executor.submit(
                      (Runnable) () -> {
                          try {
                              final byte[] bytes = readChunk();
  
                              if (bytes == null || bytes.length == 0) {
                                  // null or 0 means we reach the end of the stream, invoke the close handler.
                                  state = STATUS_CLOSED;
                                  IOUtils.closeQuietly(in);
                                  context.runOnContext(event -> {
                                      if (closeHandler != null) {
                                          closeHandler.handle(null);
                                      }
                                  });
                              } else {
                                  // We still have data, dispatch it.
                                  context.runOnContext(event -> {
                                      dataHandler.handle(Buffer.buffer(bytes));
                                      // The next chunk will be read in another call, and maybe another thread.
                                      // As the data was already given to the data handler, this is fine.
                                      doRead();
                                  });
                              }
                          } catch (final Exception e) {
                              // Error detected, invokes the failure handler.
                              state = STATUS_CLOSED;
                              IOUtils.closeQuietly(in);
                              /**
                               * Invokes the failure handler.
                               * @param event irrelevant
                               */
                              context.runOnContext(event -> {
                                  if (failureHandler != null) {
                                      failureHandler.handle(e);
                                  }
                              });
                          }
                      });
          }
      }
docs: The method actually reading the stream.
  Except the first calls, this method is executed within an Akka thread.