@Override
 public void removeTunnel(final Requests request, final PccSession session) {
   final PlspId plspId = request.getLsp().getPlspId();
   final Tunnel tunnel = this.tunnels.get(plspId);
   final long srpId = request.getSrp().getOperationId().getValue();
   if (tunnel != null) {
     if (tunnel.getType() == LspType.PCE_LSP) {
       if (hasDelegation(tunnel, session)) {
         this.tunnels.remove(plspId);
         sendToAll(
             tunnel,
             plspId,
             tunnel.getLspState().getEro().getSubobject(),
             new SrpBuilder(request.getSrp())
                 .addAugmentation(Srp1.class, new Srp1Builder().setRemove(true).build())
                 .build(),
             reqToRptPath(request),
             request.getLsp());
       } else {
         session.sendError(
             MsgBuilderUtil.createErrorMsg(PCEPErrors.UPDATE_REQ_FOR_NON_LSP, srpId));
       }
     } else {
       session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.LSP_NOT_PCE_INITIATED, srpId));
     }
   } else {
     session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UNKNOWN_PLSP_ID, srpId));
   }
 }
 @Override
 public void returnDelegation(final Updates update, final PccSession session) {
   final PlspId plspId = update.getLsp().getPlspId();
   final Tunnel tunnel = this.tunnels.get(plspId);
   final long srpId = update.getSrp().getOperationId().getValue();
   if (tunnel != null) {
     // check if session really has a delegation
     if (hasDelegation(tunnel, session)) {
       // send report D=0
       final Tlvs tlvs =
           createLspTlvs(
               plspId.getValue(),
               true,
               getDestinationAddress(tunnel.getLspState().getEro().getSubobject(), this.address),
               this.address,
               this.address,
               Optional.of(tunnel.getPathName()));
       session.sendReport(
           createPcRtpMessage(
               new LspBuilder(update.getLsp())
                   .setSync(true)
                   .setOperational(OperationalStatus.Up)
                   .setDelegate(false)
                   .setTlvs(tlvs)
                   .build(),
               Optional.of(createSrp(srpId)),
               tunnel.getLspState()));
       // start state timer
       startStateTimeout(tunnel, plspId);
       // if PCC's LSP, start re-delegation timer
       if (tunnel.getType() == LspType.PCC_LSP) {
         startRedelegationTimer(tunnel, plspId, session);
       } else {
         // if PCE-initiated LSP, revoke delegation instantly
         setDelegation(plspId, null);
       }
     } else {
       session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UPDATE_REQ_FOR_NON_LSP, srpId));
     }
   } else {
     session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UNKNOWN_PLSP_ID, srpId));
   }
 }
 @Override
 public void reportToAll(final Updates update, final PccSession session) {
   final PlspId plspId = update.getLsp().getPlspId();
   final Tunnel tunnel = this.tunnels.get(plspId);
   final long srpId = update.getSrp().getOperationId().getValue();
   if (tunnel != null) {
     if (hasDelegation(tunnel, session)) {
       final Srp srp = createSrp(update.getSrp().getOperationId().getValue());
       final Path path = updToRptPath(update.getPath());
       final List<Subobject> subobjects = update.getPath().getEro().getSubobject();
       final Lsp lsp = update.getLsp();
       sendToAll(tunnel, plspId, subobjects, srp, path, lsp);
       // update tunnel state
       tunnel.setLspState(path);
     } else {
       session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UPDATE_REQ_FOR_NON_LSP, srpId));
     }
   } else {
     session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UNKNOWN_PLSP_ID, srpId));
   }
 }
 @Override
 public void takeDelegation(final Requests request, final PccSession session) {
   final PlspId plspId = request.getLsp().getPlspId();
   final Tunnel tunnel = this.tunnels.get(plspId);
   final long srpId = request.getSrp().getOperationId().getValue();
   if (tunnel != null) {
     // check if tunnel has no delegation
     if (tunnel.type == LspType.PCE_LSP
         && (tunnel.getDelegationHolder() == -1
             || tunnel.getDelegationHolder() == session.getId())) {
       // set delegation
       tunnel.cancelTimeouts();
       setDelegation(plspId, session);
       // send report
       final Tlvs tlvs =
           createLspTlvs(
               plspId.getValue(),
               true,
               getDestinationAddress(tunnel.getLspState().getEro().getSubobject(), this.address),
               this.address,
               this.address,
               Optional.of(tunnel.getPathName()));
       session.sendReport(
           createPcRtpMessage(
               new LspBuilder(request.getLsp())
                   .setSync(true)
                   .setOperational(OperationalStatus.Up)
                   .setDelegate(true)
                   .setTlvs(tlvs)
                   .build(),
               Optional.of(createSrp(srpId)),
               tunnel.getLspState()));
     } else {
       session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.LSP_NOT_PCE_INITIATED, srpId));
     }
   } else {
     session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UNKNOWN_PLSP_ID, srpId));
   }
 }
 @Override
 public synchronized void onSessionUp(final PccSession session) {
   // first session - delegate all PCC's LSPs
   // only when reporting at startup
   if (!this.sessions.containsKey(session.getId()) && session.getId() == 0) {
     for (final PlspId plspId : this.tunnels.keySet()) {
       setDelegation(plspId, session);
     }
   }
   this.sessions.put(session.getId(), session);
   if (!this.tunnels.isEmpty()) {
     // report all known LSPs
     for (final Entry<PlspId, Tunnel> entry : this.tunnels.entrySet()) {
       final Tunnel tunnel = entry.getValue();
       final boolean delegation = hasDelegation(tunnel, session);
       if (delegation) {
         tunnel.cancelTimeouts();
       }
       final long plspId = entry.getKey().getValue();
       final Tlvs tlvs =
           MsgBuilderUtil.createLspTlvs(
               plspId,
               true,
               getDestinationAddress(tunnel.getLspState().getEro().getSubobject(), this.address),
               this.address,
               this.address,
               Optional.of(tunnel.getPathName()));
       session.sendReport(
           createPcRtpMessage(
               createLsp(plspId, true, Optional.<Tlvs>fromNullable(tlvs), delegation, false),
               NO_SRP,
               tunnel.getLspState()));
     }
     // end-of-sync marker
     session.sendReport(
         createPcRtpMessage(
             createLsp(0, false, Optional.<Tlvs>absent(), true, false),
             NO_SRP,
             createPath(Collections.<Subobject>emptyList())));
   }
 }
 public PccTunnelManagerImpl(
     final int lspsCount,
     final InetAddress address,
     final int redelegationTimeout,
     final int stateTimeout,
     final Timer timer) {
   Preconditions.checkArgument(lspsCount >= 0);
   Preconditions.checkNotNull(address);
   this.redelegationTimeout = redelegationTimeout;
   this.stateTimeout = stateTimeout;
   this.plspIDsCounter = new AtomicLong(lspsCount);
   this.address = InetAddresses.toAddrString(Preconditions.checkNotNull(address));
   this.timer = Preconditions.checkNotNull(timer);
   for (int i = 1; i <= lspsCount; i++) {
     final Tunnel tunnel =
         new Tunnel(
             MsgBuilderUtil.getDefaultPathName(this.address, i),
             PCC_DELEGATION,
             LspType.PCC_LSP,
             createPath(Lists.newArrayList(DEFAULT_ENDPOINT_HOP)));
     this.tunnels.put(new PlspId((long) i), tunnel);
   }
 }