[ONOS] PCEP provider changes, added node listeners to topology provider

Change-Id: I98bc6445ee78a8f0bf53f897f0a25f678ec7fc99
diff --git a/protocols/pcep/api/BUCK b/protocols/pcep/api/BUCK
index ae80b3a..8930a95 100644
--- a/protocols/pcep/api/BUCK
+++ b/protocols/pcep/api/BUCK
@@ -1,6 +1,7 @@
 COMPILE_DEPS = [
     '//lib:CORE_DEPS',
     '//protocols/pcep/pcepio:onos-protocols-pcep-pcepio',
+    '//apps/pcep-api:onos-apps-pcep-api',
 ]
 
 osgi_jar_with_tests (
diff --git a/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/ClientCapability.java b/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/ClientCapability.java
index e2b5092..e9cafef 100644
--- a/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/ClientCapability.java
+++ b/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/ClientCapability.java
@@ -26,6 +26,8 @@
     private boolean pceccCapability;
     private boolean statefulPceCapability;
     private boolean pcInstantiationCapability;
+    private boolean labelStackCapability;
+    private boolean srCapability;
 
     /**
      * Creates new instance of client capability.
@@ -33,11 +35,34 @@
      * @param pceccCapability represents PCECC capability
      * @param statefulPceCapability represents stateful PCE capability
      * @param pcInstantiationCapability represents PC initiation capability
+     * @param labelStackCapability represents S bit is set in PCECC capability
+     * @param srCapability represents SR capability
      */
-    public ClientCapability(boolean pceccCapability, boolean statefulPceCapability, boolean pcInstantiationCapability) {
+    public ClientCapability(boolean pceccCapability, boolean statefulPceCapability, boolean pcInstantiationCapability,
+            boolean labelStackCapability, boolean srCapability) {
         this.pceccCapability = pceccCapability;
         this.statefulPceCapability = statefulPceCapability;
         this.pcInstantiationCapability = pcInstantiationCapability;
+        this.labelStackCapability = labelStackCapability;
+        this.srCapability = srCapability;
+    }
+
+    /**
+     * Obtains label stack capability.
+     *
+     * @return true if client supports PCECC capability with S bit set otherwise false
+     */
+    public boolean labelStackCapability() {
+        return labelStackCapability;
+    }
+
+    /**
+     * Obtains segment routing capability.
+     *
+     * @return true if client supports SR capability otherwise false
+     */
+    public boolean srCapability() {
+        return srCapability;
     }
 
     /**
@@ -69,7 +94,8 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(pceccCapability, statefulPceCapability, pcInstantiationCapability);
+        return Objects.hash(pceccCapability, statefulPceCapability, pcInstantiationCapability, labelStackCapability,
+                srCapability);
     }
 
     @Override
@@ -81,7 +107,9 @@
             ClientCapability other = (ClientCapability) obj;
             return Objects.equals(pceccCapability, other.pceccCapability)
                     && Objects.equals(statefulPceCapability, other.statefulPceCapability)
-                    && Objects.equals(pcInstantiationCapability, other.pcInstantiationCapability);
+                    && Objects.equals(pcInstantiationCapability, other.pcInstantiationCapability)
+                    && Objects.equals(labelStackCapability, other.labelStackCapability)
+                    && Objects.equals(srCapability, other.srCapability);
         }
         return false;
     }
@@ -92,6 +120,8 @@
                 .add("pceccCapability", pceccCapability)
                 .add("statefulPceCapability", statefulPceCapability)
                 .add("pcInstantiationCapability", pcInstantiationCapability)
+                .add("labelStackCapability", labelStackCapability)
+                .add("srCapability", srCapability)
                 .toString();
     }
 }
\ No newline at end of file
diff --git a/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/PcepClient.java b/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/PcepClient.java
index afeeae8..6ab804c 100644
--- a/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/PcepClient.java
+++ b/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/PcepClient.java
@@ -135,4 +135,18 @@
      * @return capability supported by client
      */
     ClientCapability capability();
+
+    /**
+     * Adds PCEP device when session is successfully established.
+     *
+     * @param pc PCEP client details
+     */
+    void addNode(PcepClient pc);
+
+    /**
+     * Removes PCEP device when session is disconnected.
+     *
+     * @param pccId PCEP client ID
+     */
+    void deleteNode(PccId pccId);
 }
diff --git a/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/PcepClientController.java b/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/PcepClientController.java
index befc3f0..fff6759 100644
--- a/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/PcepClientController.java
+++ b/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/PcepClientController.java
@@ -57,7 +57,7 @@
     void removeListener(PcepClientListener listener);
 
     /**
-     * Register a listener for OF msg events.
+     * Register a listener for PCEP msg events.
      *
      * @param listener the listener to notify
      */
@@ -71,6 +71,20 @@
     void removeEventListener(PcepEventListener listener);
 
     /**
+     * Register a listener for PCEP msg events[carrying node descriptor details].
+     *
+     * @param listener the listener to notify
+     */
+    void addNodeListener(PcepNodeListener listener);
+
+    /**
+     * Unregister a listener.
+     *
+     * @param listener the listener to be unregistered
+     */
+    void removeNodeListener(PcepNodeListener listener);
+
+    /**
      * Send a message to a particular pcc client.
      *
      * @param pccId the id of the client to send message.
diff --git a/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/PcepNodeListener.java b/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/PcepNodeListener.java
new file mode 100644
index 0000000..a02a744
--- /dev/null
+++ b/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/PcepNodeListener.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.pcep.controller;
+
+/**
+ * Notifies providers about PCEP node events.
+ */
+public interface PcepNodeListener {
+
+    /**
+     * Notifies that the node was added.
+     *
+     * @param pc PCEP client details
+     */
+    void addNode(PcepClient pc);
+
+    /**
+     * Notifies that the node was removed.
+     *
+     * @param pccId PCEP client ID
+     */
+    void deleteNode(PccId pccId);
+}
diff --git a/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/driver/PcepAgent.java b/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/driver/PcepAgent.java
index 2dc3e75..de95962 100755
--- a/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/driver/PcepAgent.java
+++ b/protocols/pcep/api/src/main/java/org/onosproject/pcep/controller/driver/PcepAgent.java
@@ -60,4 +60,17 @@
      */
     void processPcepMessage(PccId pccId, PcepMessage m);
 
+    /**
+     * Adds PCEP device when session is successfully established.
+     *
+     * @param pc PCEP client details
+     */
+    void addNode(PcepClient pc);
+
+    /**
+     * Removes PCEP device when session is disconnected.
+     *
+     * @param pccId PCEP client ID
+     */
+    void deleteNode(PccId pccId);
 }
diff --git a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepChannelHandler.java b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepChannelHandler.java
index 744731f..bbad497 100644
--- a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepChannelHandler.java
+++ b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepChannelHandler.java
@@ -55,6 +55,7 @@
 import org.onosproject.pcepio.types.IPv4RouterIdOfLocalNodeSubTlv;
 import org.onosproject.pcepio.types.NodeAttributesTlv;
 import org.onosproject.pcepio.types.PceccCapabilityTlv;
+import org.onosproject.pcepio.types.SrPceCapabilityTlv;
 import org.onosproject.pcepio.types.StatefulPceCapabilityTlv;
 import org.onosproject.pcepio.types.PcepErrorDetailInfo;
 import org.onosproject.pcepio.types.PcepValueType;
@@ -260,6 +261,8 @@
                         disconnectDuplicate(h);
                     } else {
                         h.setState(ESTABLISHED);
+                        //Session is established, add a PCEP device
+                        h.addNode();
                     }
                 }
             }
@@ -469,6 +472,20 @@
     }
 
     /**
+     * Adds PCEP device once session is established.
+     */
+    private void addNode() {
+        pc.addNode(pc);
+    }
+
+    /**
+     * Deletes PCEP device when session is disconnected.
+     */
+    private void deleteNode() {
+        pc.deleteNode(pc.getPccId());
+    }
+
+    /**
      * Return a string describing this client based on the already available
      * information (ip address and/or remote socket).
      *
@@ -523,6 +540,8 @@
         boolean pceccCapability = false;
         boolean statefulPceCapability = false;
         boolean pcInstantiationCapability = false;
+        boolean labelStackCapability = false;
+        boolean srCapability = false;
 
         ListIterator<PcepValueType> listIterator = tlvList.listIterator();
         while (listIterator.hasNext()) {
@@ -531,6 +550,9 @@
             switch (tlv.getType()) {
             case PceccCapabilityTlv.TYPE:
                 pceccCapability = true;
+                if (((PceccCapabilityTlv) tlv).sBit()) {
+                    labelStackCapability = true;
+                }
                 break;
             case StatefulPceCapabilityTlv.TYPE:
                 statefulPceCapability = true;
@@ -539,11 +561,15 @@
                     pcInstantiationCapability = true;
                 }
                 break;
+            case SrPceCapabilityTlv.TYPE:
+                srCapability = true;
+                break;
             default:
                 continue;
             }
         }
-        this.capability = new ClientCapability(pceccCapability, statefulPceCapability, pcInstantiationCapability);
+        this.capability = new ClientCapability(pceccCapability, statefulPceCapability, pcInstantiationCapability,
+                labelStackCapability, srCapability);
     }
 
     /**
@@ -563,6 +589,8 @@
      */
     private void sendErrMsgAndCloseChannel() {
         // TODO send error message
+        //Remove PCEP device from topology
+        deleteNode();
         channel.close();
     }
 
diff --git a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientControllerImpl.java b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientControllerImpl.java
index 1f58bed..19e2ce4 100644
--- a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientControllerImpl.java
+++ b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientControllerImpl.java
@@ -25,12 +25,16 @@
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
 import org.apache.felix.scr.annotations.Service;
+import org.onosproject.net.device.DeviceService;
 import org.onosproject.pcep.controller.PccId;
 import org.onosproject.pcep.controller.PcepClient;
 import org.onosproject.pcep.controller.PcepClientController;
 import org.onosproject.pcep.controller.PcepClientListener;
 import org.onosproject.pcep.controller.PcepEventListener;
+import org.onosproject.pcep.controller.PcepNodeListener;
 import org.onosproject.pcep.controller.driver.PcepAgent;
 import org.onosproject.pcepio.protocol.PcepError;
 import org.onosproject.pcepio.protocol.PcepErrorInfo;
@@ -55,6 +59,9 @@
 
     private static final Logger log = LoggerFactory.getLogger(PcepClientControllerImpl.class);
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DeviceService deviceService;
+
     protected ConcurrentHashMap<PccId, PcepClient> connectedClients =
             new ConcurrentHashMap<>();
 
@@ -62,6 +69,7 @@
     protected Set<PcepClientListener> pcepClientListener = new HashSet<>();
 
     protected Set<PcepEventListener> pcepEventListener = Sets.newHashSet();
+    protected Set<PcepNodeListener> pcepNodeListener = Sets.newHashSet();
 
     private final Controller ctrl = new Controller();
 
@@ -117,6 +125,16 @@
     }
 
     @Override
+    public void addNodeListener(PcepNodeListener listener) {
+        pcepNodeListener.add(listener);
+    }
+
+    @Override
+    public void removeNodeListener(PcepNodeListener listener) {
+        pcepNodeListener.remove(listener);
+    }
+
+    @Override
     public void processClientMessage(PccId pccId, PcepMessage msg) {
         PcepClient pc = getClient(pccId);
 
@@ -173,6 +191,8 @@
             break;
         case LABEL_RANGE_RESERV:
             break;
+        case LS_REPORT: //TODO: need to handle LS report to add or remove node
+            break;
         case MAX:
             break;
         case END:
@@ -270,5 +290,19 @@
         public void processPcepMessage(PccId pccId, PcepMessage m) {
             processClientMessage(pccId, m);
         }
+
+        @Override
+        public void addNode(PcepClient pc) {
+            for (PcepNodeListener l : pcepNodeListener) {
+                l.addNode(pc);
+            }
+        }
+
+        @Override
+        public void deleteNode(PccId pccId) {
+            for (PcepNodeListener l : pcepNodeListener) {
+                l.deleteNode(pccId);
+            }
+        }
     }
 }
diff --git a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientImpl.java b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientImpl.java
index 8328f2b..6f2d8fd 100644
--- a/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientImpl.java
+++ b/protocols/pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientImpl.java
@@ -26,6 +26,7 @@
 import org.onlab.packet.IpAddress;
 import org.onosproject.pcep.controller.ClientCapability;
 import org.onosproject.pcep.controller.PccId;
+import org.onosproject.pcep.controller.PcepClient;
 import org.onosproject.pcep.controller.PcepPacketStats;
 import org.onosproject.pcep.controller.PcepSyncStatus;
 import org.onosproject.pcep.controller.driver.PcepAgent;
@@ -203,6 +204,16 @@
     }
 
     @Override
+    public void addNode(PcepClient pc) {
+        this.agent.addNode(pc);
+    }
+
+    @Override
+    public void deleteNode(PccId pccId) {
+        this.agent.deleteNode(pccId);
+    }
+
+    @Override
     public final boolean connectClient() {
         return this.agent.addConnectedClient(pccId, this);
     }