/** {@inheritDoc} */
        @Override
        public void onMessage(GridNioSession ses, HadoopMessage msg) {
          notifyListener(ses.<HadoopProcessDescriptor>meta(PROCESS_META), msg);

          if (msgQueueLimit > 0) {
            GridNioMessageTracker tracker = ses.meta(TRACKER_META);

            assert tracker != null : "Missing tracker for limited message queue: " + ses;

            tracker.run();
          }
        }
    /** {@inheritDoc} */
    @Override
    public void onMessageReceived(GridNioSession ses, Object msg) throws IgniteCheckedException {
      HadoopProcessDescriptor desc = ses.meta(PROCESS_META);

      UUID rmtProcId = desc == null ? null : desc.processId();

      if (rmtProcId == null) {
        if (!(msg instanceof ProcessHandshakeMessage)) {
          log.warning(
              "Invalid handshake message received, will close connection [ses="
                  + ses
                  + ", msg="
                  + msg
                  + ']');

          ses.close();

          return;
        }

        ProcessHandshakeMessage nId = (ProcessHandshakeMessage) msg;

        if (log.isDebugEnabled())
          log.debug("Received handshake message [ses=" + ses + ", msg=" + msg + ']');

        ses.addMeta(PROCESS_META, nId.processDescriptor());

        if (!ses.accepted())
          // Send handshake reply.
          ses.send(locIdMsg);
        else {
          //
          rmtProcId = nId.processDescriptor().processId();

          if (log.isDebugEnabled()) log.debug("Finished handshake with remote client: " + ses);

          Object sync = locks.tryLock(rmtProcId);

          if (sync != null) {
            try {
              if (clients.get(rmtProcId) == null) {
                if (log.isDebugEnabled())
                  log.debug("Will reuse session for descriptor: " + rmtProcId);

                // Handshake finished flag is true.
                clients.put(rmtProcId, new HadoopTcpNioCommunicationClient(ses));
              } else {
                if (log.isDebugEnabled())
                  log.debug(
                      "Will not reuse client as another already exists [locProcDesc="
                          + locProcDesc
                          + ", desc="
                          + desc
                          + ']');
              }
            } finally {
              locks.unlock(rmtProcId, sync);
            }
          } else {
            if (log.isDebugEnabled())
              log.debug(
                  "Concurrent connection is being established, will not reuse client session ["
                      + "locProcDesc="
                      + locProcDesc
                      + ", desc="
                      + desc
                      + ']');
          }
        }

        if (log.isDebugEnabled())
          log.debug(
              "Handshake is finished for session [ses="
                  + ses
                  + ", locProcDesc="
                  + locProcDesc
                  + ']');

        HandshakeFinish to = ses.meta(HANDSHAKE_FINISH_META);

        if (to != null) to.finish();

        // Notify session opened (both parties).
        proceedSessionOpened(ses);
      } else {
        if (msgQueueLimit > 0) {
          GridNioMessageTracker tracker = ses.meta(TRACKER_META);

          if (tracker == null) {
            GridNioMessageTracker old =
                ses.addMeta(TRACKER_META, tracker = new GridNioMessageTracker(ses, msgQueueLimit));

            assert old == null;
          }

          tracker.onMessageReceived();
        }

        proceedMessageReceived(ses, msg);
      }
    }