/**
   * Method writes the {@link WritableMessage} to the specific address.
   *
   * @param connection the {@link org.glassfish.grizzly.Connection} to write to
   * @param dstAddress the destination address the <tt>message</tt> will be sent to
   * @param message the {@link WritableMessage}, from which the data will be written
   * @param completionHandler {@link org.glassfish.grizzly.CompletionHandler}, which will get
   *     notified, when write will be completed
   */
  public void write(
      Connection<SocketAddress> connection,
      SocketAddress dstAddress,
      WritableMessage message,
      CompletionHandler<WriteResult<WritableMessage, SocketAddress>> completionHandler,
      final org.glassfish.grizzly.asyncqueue.PushBackHandler pushBackHandler,
      long timeout,
      TimeUnit timeunit) {

    if (message == null) {
      failure(new IllegalStateException("Message cannot be null"), completionHandler);
      return;
    }

    if (connection == null || !(connection instanceof NIOConnection)) {
      failure(
          new IllegalStateException("Connection should be NIOConnection and cannot be null"),
          completionHandler);
      return;
    }

    final NIOConnection nioConnection = (NIOConnection) connection;

    final WriteResult<WritableMessage, SocketAddress> writeResult =
        WriteResult.create(connection, message, dstAddress, 0);

    try {
      write0(nioConnection, dstAddress, message, writeResult, timeout, timeunit);

      // Call PushBackHandler after data is written.
      // IMO It has more sense for blocking case
      if (pushBackHandler != null) {
        pushBackHandler.onAccept(connection, message);
      }

      if (completionHandler != null) {
        completionHandler.completed(writeResult);
      }

      message.release();
    } catch (IOException e) {
      failure(e, completionHandler);
    }
  }