docs: private boolean writeFrameSync() throws FlowControlException {
          if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
              Tr.debug(tc, "writeFrameSync entry: stream: " + myID);
          }
          Frame currentFrame = this.currentFrame;
  
          if (!currentFrame.getFrameType().equals(FrameTypes.GOAWAY) && isStreamClosed()) {
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                  Tr.debug(tc, "writeFrameSync exit - stream " + myID + " is closed");
              }
              return false;
          }
          if (currentFrame.isWriteFrame() && currentFrame.getInitialized()) {
              WsByteBuffer writeFrameBuffer = null;
              WsByteBuffer[] writeFrameBuffers = null;
              try {
                  if (currentFrame.getFrameType() == FrameTypes.DATA) {
                      FrameData data = (FrameData) currentFrame;
                      boolean timedOut = false;
  
                      // Check to see if the write window is large enough to write this data.
                      if (isWindowLimitExceeded((FrameData) currentFrame)) {
                          // the connection or stream window is too small to write this data frame.  This thread will wait for a max of
                          // 5 seconds for a window update that's large enough to allow the data frame to be written out
                          long startTime = System.currentTimeMillis();
                          while (isWindowLimitExceeded((FrameData) currentFrame) && !timedOut) {
                              synchronized (this) {
                                  this.wait(MAX_TIME_TO_WAIT_FOR_WINDOW_UPDATE_MS);
                              }
                              if (state.equals(StreamState.CLOSED) || muxLink.checkIfGoAwaySendingOrClosing()) {
                                  return false;
                              } else if (System.currentTimeMillis() - startTime > MAX_TIME_TO_WAIT_FOR_WINDOW_UPDATE_MS) {
                                  timedOut = true;
                              }
                          }
                      }
                      // the flow control window is large enough to write the data frame
                      if (!timedOut) {
                          writeFrameBuffers = data.buildFrameArrayForWrite();
                          muxLink.writeSync(null, writeFrameBuffers, data.getWriteFrameLength(), TCPRequestContext.NO_TIMEOUT,
                                            data.getFrameType(), data.getPayloadLength(), myID);
  
                          streamWindowUpdateWriteLimit -= currentFrame.getPayloadLength();
                          if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                              Tr.debug(tc, "stream: " + myID + " Data payload written - new streamWindowUpdateWriteLimit: " + streamWindowUpdateWriteLimit);
                          }
  
                      } else {
                          // timed out waiting for a window update, throw FCE which will cause this stream to be RESET.
                          FlowControlException up = new FlowControlException("Write failed. Window limit exceeded. Stream will be Reset.");
                          up.setConnectionError(false);
                          throw up;
                      }
  
                  } else {
                      // this frame is not a data frame, and so it's not subject to flow control and we can write immediately
                      writeFrameBuffer = currentFrame.buildFrameForWrite();
                      muxLink.writeSync(writeFrameBuffer, null, currentFrame.getWriteFrameLength(), TCPRequestContext.NO_TIMEOUT,
                                        currentFrame.getFrameType(), currentFrame.getPayloadLength(), myID);
                  }
              } catch (IOException e) {
                  if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                      Tr.debug(tc, "writeFrameSync caught an IOException: " + e);
                  }
  
              } catch (InterruptedException e) {
                  if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                      Tr.debug(tc, "writeFrameSync interrupted: " + e);
                  }
              } finally {
                  // release buffer used to synchronously write the frame
                  if (writeFrameBuffer != null) {
                      writeFrameBuffer.release();
                  } else if (writeFrameBuffers != null) {
                      for (int i = 0; i < writeFrameBuffers.length; i++) {
                          if (writeFrameBuffers[i] != null) {
                              // buffer at [1] is allocated by old channel code, it will clean it up
                              // later move this logic to a frame cleanup method that can take care of releasing
                              if (i != 1) {
                                  writeFrameBuffers[i].release();
                              }
                          }
                      }
                  }
              }
  
          } else {
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                  Tr.debug(tc, "writeFrameSync internal flow issue - exiting method ");
              }
          }
          if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
              Tr.debug(tc, "writeFrameSync exit: stream-id: " + myID);
          }
          return true;
      }