code: public void processNack(ControlNack nm)
      throws SIResourceException
    {
      if (tc.isEntryEnabled())
            SibTr.entry(tc, "processNack", nm);
   
      long startstamp = nm.getStartTick();
      long endstamp = nm.getEndTick();
  
      synchronized (this)
      {
        // the following steps are performed:
        // (1) check ticks in Unknown
        // (2) create nacks when appropriate
        // (3) change Unknown ticks to Requested
        // (4) send nacks.
  
        iststream.setCursor(startstamp);
        boolean changed = false;
        TickRange tr = iststream.getNext();
        TickRange tr2;
  
        do
        {
          // look at each TickRange individually
          // and send nacks for ranges that are not already in Requested state
          if (tr.type == TickRange.Unknown)
          {
            changed = true;
            long maxStartstamp = max(tr.startstamp, startstamp);
            long minEndstamp = min(tr.endstamp, endstamp);
          
            upControl.sendNackMessage(null, null, null, maxStartstamp, minEndstamp, priority, reliability, streamID);
          }
  
          tr2 = tr;
          tr = iststream.getNext();
        }
        while ((tr.startstamp <= endstamp) && (tr2 != tr));
  
        if (changed)
        {
          // update the stream to Requested
          tr = new TickRange(TickRange.Requested, startstamp, endstamp);
          iststream.writeRange(tr);
  
          // start a timer to forget this Request 
          new ReqExpiryHandle(tr);
        }
  
      } // end synchronized (this)
     
      if (tc.isEntryEnabled())
        SibTr.exit(tc, "processNack");
    }
docs: This method sends Nacks for any ticks within the range
  startstamp to endstamp which are in Unknown state
  Those in Requested should already be being satisfied