private void acceptMessage(byte[] bytes) {
   try {
     received.offer((Message) serializer.deserialize(bytes));
   } catch (IOException | ClassCastException e) {
     logger.trace("Got some trash");
   }
 }
  /**
   * Sends a message.
   *
   * <p>Current thread is NOT blocked by this method call. But no two response-actions (onReceive or
   * onFail on any request) or response protocols will be executed at same time, so you can write
   * not thread-safe code inside them.
   *
   * <p>
   *
   * <p>This gets being very similar to automaton programming :)
   *
   * @param address receiver of message
   * @param message mail entry
   * @param type way of sending a message: TCP, single UPD...
   * @param timeout timeout in milliseconds
   * @param receiveListener an action to invoke when got an answer.
   * @param failListener an action to invoke when timeout exceeded.
   * @param <ReplyType> response message type
   */
  public <ReplyType extends ResponseMessage> void send(
      InetSocketAddress address,
      RequestMessage<ReplyType> message,
      DispatchType type,
      int timeout,
      ReceiveListener<ReplyType> receiveListener,
      FailListener failListener) {
    BlockingQueue<ResponseMessage> responseContainer = submit(address, message, type);

    // TODO: make in single thread
    scheduledExecutor.schedule(
        () -> {
          //noinspection unchecked
          ReplyType response = (ReplyType) responseContainer.poll();
          if (response != null) receiveListener.onReceive(address, response);
          else failListener.onFail(address);
        },
        timeout,
        TimeUnit.MILLISECONDS);
    // TODO: clear responseWaiters map
  }
  private void forwardSingle(
      InetSocketAddress address, Message message, DispatchType dispatchType) {
    if (dispatchType == DispatchType.LOOPBACK) {
      received.offer(message);
      return;
    }

    SendInfo sendInfo = toSendableForm(address, message);
    if (dispatchType == DispatchType.PLAIN) {
      udpDispatcher.send(sendInfo);
    } else if (dispatchType == DispatchType.SAFE) {
      tcpDispatcher.send(sendInfo);
    } else {
      throw new IllegalArgumentException("Can't process dispatch type of " + dispatchType);
    }
  }