docs: private int processWrite(int state, final Object userData, int pos, int length) throws IOException {
          if (done || exchange == null) {
              throw new ClosedChannelException();
          }
          try {
              assert state != STATE_BODY;
              if (state == STATE_BUF_FLUSH) {
                  final ByteBuffer byteBuffer = pooledBuffer.getBuffer();
                  do {
                      long res = 0;
                      ByteBuffer[] data;
                      if (userData == null || length == 0) {
                          res = next.write(byteBuffer);
                      } else if (userData instanceof ByteBuffer) {
                          data = writevBuffer;
                          if (data == null) {
                              data = writevBuffer = new ByteBuffer[2];
                          }
                          data[0] = byteBuffer;
                          data[1] = (ByteBuffer) userData;
                          res = next.write(data, 0, 2);
                      } else {
                          data = writevBuffer;
                          if (data == null || data.length < length + 1) {
                              data = writevBuffer = new ByteBuffer[length + 1];
                          }
                          data[0] = byteBuffer;
                          System.arraycopy(userData, pos, data, 1, length);
                          res = next.write(data, 0, length + 1);
                      }
                      if (res == 0) {
                          return STATE_BUF_FLUSH;
                      }
                  } while (byteBuffer.hasRemaining());
                  bufferDone();
                  return STATE_BODY;
              } else if (state != STATE_START) {
                  return processStatefulWrite(state, userData, pos, length);
              }
  
              //merge the cookies into the header map
              Connectors.flattenCookies(exchange);
  
              if (pooledBuffer == null) {
                  pooledBuffer = pool.allocate();
              }
              ByteBuffer buffer = pooledBuffer.getBuffer();
  
  
              assert buffer.remaining() >= 50;
              Protocols.HTTP_1_1.appendTo(buffer);
              buffer.put((byte) ' ');
              int code = exchange.getStatusCode();
              assert 999 >= code && code >= 100;
              buffer.put((byte) (code / 100 + '0'));
              buffer.put((byte) (code / 10 % 10 + '0'));
              buffer.put((byte) (code % 10 + '0'));
              buffer.put((byte) ' ');
  
              String string = exchange.getReasonPhrase();
              if(string == null) {
                  string = StatusCodes.getReason(code);
              }
              if(string.length() > buffer.remaining()) {
                  pooledBuffer.close();
                  pooledBuffer = null;
                  truncateWrites();
                  throw UndertowMessages.MESSAGES.reasonPhraseToLargeForBuffer(string);
              }
              writeString(buffer, string);
              buffer.put((byte) '\r').put((byte) '\n');
  
              int remaining = buffer.remaining();
  
  
              HeaderMap headers = exchange.getResponseHeaders();
              long fiCookie = headers.fastIterateNonEmpty();
              while (fiCookie != -1) {
                  HeaderValues headerValues = headers.fiCurrent(fiCookie);
  
                  HttpString header = headerValues.getHeaderName();
                  int headerSize = header.length();
                  int valueIdx = 0;
                  while (valueIdx < headerValues.size()) {
                      remaining -= (headerSize + 2);
  
                      if (remaining < 0) {
                          this.fiCookie = fiCookie;
                          this.string = string;
                          this.headerValues = headerValues;
                          this.valueIdx = valueIdx;
                          this.charIndex = 0;
                          this.state = STATE_HDR_NAME;
                          buffer.flip();
                          return processStatefulWrite(STATE_HDR_NAME, userData, pos, length);
                      }
                      header.appendTo(buffer);
                      buffer.put((byte) ':').put((byte) ' ');
                      string = headerValues.get(valueIdx++);
  
                      remaining -= (string.length() + 2);
                      if (remaining < 2) {//we use 2 here, to make sure we always have room for the final \r\n
                          this.fiCookie = fiCookie;
                          this.string = string;
                          this.headerValues = headerValues;
                          this.valueIdx = valueIdx;
                          this.charIndex = 0;
                          this.state = STATE_HDR_VAL;
                          buffer.flip();
                          return processStatefulWrite(STATE_HDR_VAL, userData, pos, length);
                      }
                      writeString(buffer, string);
                      buffer.put((byte) '\r').put((byte) '\n');
                  }
                  fiCookie = headers.fiNextNonEmpty(fiCookie);
              }
              buffer.put((byte) '\r').put((byte) '\n');
              buffer.flip();
              do {
                  long res = 0;
                  ByteBuffer[] data;
                  if (userData == null) {
                      res = next.write(buffer);
                  } else if (userData instanceof ByteBuffer) {
                      data = writevBuffer;
                      if (data == null) {
                          data = writevBuffer = new ByteBuffer[2];
                      }
                      data[0] = buffer;
                      data[1] = (ByteBuffer) userData;
                      res = next.write(data, 0, 2);
                  } else {
                      data = writevBuffer;
                      if (data == null || data.length < length + 1) {
                          data = writevBuffer = new ByteBuffer[length + 1];
                      }
                      data[0] = buffer;
                      System.arraycopy(userData, pos, data, 1, length);
                      res = next.write(data, 0, length + 1);
                  }
                  if (res == 0) {
                      return STATE_BUF_FLUSH;
                  }
              } while (buffer.hasRemaining());
              bufferDone();
              return STATE_BODY;
          } catch (IOException | RuntimeException | Error e) {
              //WFLY-4696, just to be safe
              if (pooledBuffer != null) {
                  pooledBuffer.close();
                  pooledBuffer = null;
              }
              throw e;
          }
      }