protected void copy() throws Exception {
    Buffer buf;
    long transferred = 0;

    while ((buf = reader.read()) != null) {
      transferred += buf.getLength();
      sink.write(buf);
    }
    logger.debug("finished receiving data; received " + transferred + " bytes");
  }
  protected void shutdown(Object quitToken) throws IOException {
    logger.debug("shutdown");

    reader.close();

    // garbage collect the socket
    socketBox.setSocket(null);

    // data sink is shared by all data channels,
    // so should be closed by the last one exiting
    if (quitToken != null) {
      sink.close();
    }
  }