/**
  * Checks if the the kenel listening on the SocketKernel has already been added to the routing
  * Table.
  *
  * @param distantKernel SocketKernel of the distant Kernel
  * @return true iff the kenel listening on the SocketKernel <code>distantKernel</code> is known
  */
 private boolean isKnownKernelSocket(SocketKernel distantKernel) {
   Iterator it = routeTable.values().iterator();
   while (it.hasNext()) {
     DistantKernelInformation element = (DistantKernelInformation) it.next();
     if (element.getSocketKernel().equals(distantKernel)) return true;
   }
   return false;
 }
  /* (non-Javadoc)
   * @see madkit.netcomm.MadkitNetworkAgent#handleNetworkMessage(madkit.netcomm.NetworkMessage)
   */
  protected void handleNetworkMessage(NetworkMessage message) {
    switch (message.getType()) {
      case NetworkMessage.SYNCH_REQUEST:
        debug("handling NetworkMessage.SYNCH_REQUEST");
        Vector vec = (Vector) message.getArgument();
        handleSynchRequest(message.getSender(), vec);
        break;
      case NetworkMessage.ROUTE_MESSAGE:
        debug("Routing message");
        sendDistantMessage((KernelMessage) message.getArgument());
        break;

      case NetworkMessage.CONNECT_KERNEL:
        debug("CONNECT_KERNEL received");
        Vector v1 = (Vector) message.getArgument();
        Socket brSocket = (Socket) v1.get(0);
        KernelAddress id = (KernelAddress) v1.get(1); // check if the kernel is known
        SocketKernel distantSK = (SocketKernel) v1.get(2);

        if (id != null && routeTable.containsKey(id)) {
          debug("broadcast from known kernel");
          try {
            brSocket.close();
          } catch (IOException e) {
            debug(e.toString());
          }
          break;
        }
        launchNetConfigConnection(distantSK, brSocket, id);
        break;
      case NetworkMessage.KERNEL_DISCONNECTED:
        routeTable.remove(((KernelAddress) message.getArgument()).getID());
        break;
      case NetworkMessage.UPDATE_ROUTE:
        debug("UPDATE_ROUTE");
        Vector v = (Vector) message.getArgument();
        KernelAddress addr = (KernelAddress) v.get(0);
        AgentAddress p2p = (AgentAddress) v.get(1);
        DistantKernelInformation info = (DistantKernelInformation) routeTable.remove(addr.getID());
        info.setP2PAgent(p2p);
        info.setProtocol((String) v.get(2));
        routeTable.put(addr.getID(), info);
        sendMessage(
            getAgentWithRole(community, group, "netagent"),
            new NetworkMessage(NetworkMessage.UPDATE_ROUTE, v));
        sendMessage(
            message.getSender(), new NetworkMessage(NetworkMessage.UPDATE_ROUTE_DONE, addr));
        break;
      default:
        debug("unknown NetworkMessage Received");
        debug(message.toString());
        break;
    }
  }
 /**
  * Added by Saber @If a new agency is added or an agency is moved the agencyKeeper must update his
  * agencyTable
  */
 private void updateDistantAgencies() {
   Vector agenciesInformations = new Vector(1, 1);
   Iterator it = routeTable.values().iterator();
   while (it.hasNext()) {
     DistantKernelInformation element = (DistantKernelInformation) it.next();
     agenciesInformations.addElement(element.getDistantKernelAddress());
   }
   //	try {
   sendMessage(
       getAgentWithRole("system", "AgencyKeeper"),
       new NetworkRequest(NetworkMessage.UPDATE_AGENCIES_INFORMATIONS, agenciesInformations));
   //		} catch (MessageException e) {
   //			if(getDebug()){
   //			debug(e.toString());
   //			e.printStackTrace();
   //			}
   //		}
 }
  /**
   * Sends a message to a Distant Kernel.
   *
   * @param message message to send.
   */
  private void sendDistantMessage(KernelMessage message) {
    Message orig;
    if (message instanceof KernelMessage) {
      KernelMessage temp = (KernelMessage) message;
      orig = (Message) (temp.getArgument());
    } else orig = message;

    if (shouldUseUDP(orig)) {
      println("WARN:  No udp message routing yet!!!");
    } else {
      DistantKernelInformation info = getP2PAddress(orig);
      if (info != null) {
        AgentAddress p2p = info.getP2PAgent();
        sendMessage(p2p, new NetworkMessage(NetworkMessage.DISTANT_MESSAGE, orig));
      } else {
        println("WARN : unknown destination kernel" + orig.getReceiver().getKernel());
      }
    }
  }
 /**
  * Handles a request of a P2PAgent.<br>
  * The vector must contain:<br>
  * the KernelAddress<br>
  * the Distant SocketKernel<br>
  * the AgentAdress of the distant Kernel<br>
  * the Connection protocol<br>
  * the Kernels known by the distant kernel.This can be either the DistantKernelInFormation (used
  * by netcomm) or just the socketKernel. (for compatibility with 3.1)<br>
  *
  * @param address AgentAddress of the P2PAgent requesting the Sync
  * @param vec Information to sync
  */
 private void handleSynchRequest(AgentAddress sender, Vector vec) {
   Enumeration a = vec.elements();
   KernelAddress distantK = (KernelAddress) a.nextElement();
   SocketKernel distantSI = (SocketKernel) a.nextElement();
   AgentAddress distantKernel = (AgentAddress) a.nextElement();
   String protocol = (String) a.nextElement();
   Collection otherKernels = (Collection) a.nextElement();
   if (addRoute(distantK, sender, distantSI, protocol)) // el de ack
   {
     replyConnect(sender);
     for (Iterator i = otherKernels.iterator(); i.hasNext(); ) {
       Object o = i.next();
       if (o instanceof DistantKernelInformation) {
         DistantKernelInformation distantInfo = (DistantKernelInformation) o;
         if (!(myKernel.getKernel().getID().equals(distantInfo.getDistantKernelAddress().getID())
             || isConfiguring(distantInfo.getDistantKernelAddress())
             || isKnownKernelSocket(distantInfo.getSocketKernel()))) {
           launchNetConfigConnection(
               distantInfo.getSocketKernel(), null, distantInfo.getDistantKernelAddress());
         }
       } else if (o instanceof SocketKernel) {
         SocketKernel distantSocket = (SocketKernel) o;
         if (!(myInfo.equals(distantSocket) || isKnownKernelSocket(distantSocket))) {
           launchNetConfigConnection(distantSocket, null, null);
         }
       }
     }
   } else {
     debug("Adding Route failed");
     if (!sender.equals(
         getP2PAddress(distantK))) // kill the agent.. the route is handled by someone else
     sendMessage(sender, new NetworkMessage(NetworkMessage.DIE, null));
   }
 }
  /**
   * Adds a route to the routing table. Before adding a new kernel, it checks if the kernel's ID
   * already existes in the routing table. if it does, no action is taken and returns false.
   *
   * @param ka KernelAddress of the distant kernel to add.
   * @param addr AgentAddress of the P2PAgent responsable for the connection with the kernel
   * @param dkinfo SocketKernel of the distant Kernel
   * @return true iff the distant kernel was add. false if the kernel already has an entry in the
   *     route table
   */
  private boolean addRoute(
      KernelAddress ka, AgentAddress addr, SocketKernel dkinfo, String protocol) {
    DistantKernelInformation tmp = (DistantKernelInformation) routeTable.get(ka.getID());
    if (tmp != null) {
      if (tmp.getProtocol().equals(CONFIG)) {
        if (protocol.equals(CONFIG)) {
          // Added by saber
          KernelAddress agency = tmp.getDistantKernelAddress();
          if (!agency.getKernelName().equals(ka.getKernelName())
              || (agency.supportMobility()
                  != ka.supportMobility())) // the distantKernel has changed its name or mobility
          // aspect
          {
            agency.setKernelName(ka.getKernelName());
            if (ka.supportMobility()) agency.enableMobility();
            else agency.disableMobility();
            return true;
          } else // end of saber modification
          return false;
        } else {
          routeTable.remove(ka.getID());
          updateDistantAgencies();
        }
      } else {
        debug("Kernel " + ka + " already added");
        return false;
      }
    }

    debug("adding new kernel " + ka.getID());
    routeTable.put(ka.getID(), new DistantKernelInformation(ka, addr, dkinfo, protocol));
    updateDistantAgencies();

    if (!protocol.equals(CONFIG)) sendConnectedKernelInformation(dkinfo, ka, addr, protocol);
    return true;
  }
  /** Create a Vector Compatible with Madkit 3.1 */
  private Vector buildSynch(char s, HashSet dKernels) {
    Vector v = new Vector();

    if (s == 'c') v.addElement("TRANSMIT_SOCKET_INFO");
    else if (s == 'r') v.addElement("ACK_SOCKET_INFO");

    v.addElement(getAddress().getKernel());
    madkit.communicator.SocketKernel sktemp =
        new madkit.communicator.SocketKernel(myInfo.getHost(), myInfo.getPort());
    v.addElement(sktemp); // need to change the socketKernel object to keep backwards comp
    v.addElement(myKernel);
    Collection scks = new Vector();
    for (Iterator iter = dKernels.iterator(); iter.hasNext(); ) {
      DistantKernelInformation info = (DistantKernelInformation) iter.next();
      madkit.communicator.SocketKernel sk =
          new madkit.communicator.SocketKernel(
              info.getSocketKernel().getHost(),
              info.getSocketKernel()
                  .getPort()); // need to change the socketKernel object to keep backwards comp
      scks.add(sk);
    }
    v.addElement(new HashSet(scks));
    return v;
  }
 private AgentAddress getP2PAddress(KernelAddress kernelAddress) {
   DistantKernelInformation info =
       (DistantKernelInformation) routeTable.get(kernelAddress.getID());
   return info.getP2PAgent();
 }