public void handleUpdatePacket(Packet p, String from) {
    // dont update packets that came from this device
    if (p.getSource().equals(localDevice.getBluetoothAddress())) return;

    // get the md5 of the payload of the packet and store it
    // if the previous md5 is the same with the new one
    // then this packet is redundant
    String hash = md5(p.getPayload());
    if (history.containsKey(p.getSource())) {
      String old = history.get(p.getSource());
      if (old.equals(hash)) return;
    }

    ByteBuffer buffer = ByteBuffer.allocate(p.getPayload().length);
    buffer.put(p.getPayload());
    routingTable.remove(p.getSource());
    routingTable.add(p.getSource());
    byte[] tmp = new byte[12];
    while (buffer.hasRemaining()) {
      buffer.get(tmp, 0, 12);
      routingTable.add(p.getSource(), new String(tmp));
    }

    for (String address : connections.keySet()) {
      if (!address.equals(from)) {
        connections.get(address).offer(p);
      }
    }
    history.put(p.getSource(), hash);
  }
 public Set<String> getConnections() {
   mutex.readLock().lock();
   try {
     return routingTable.devices(localDevice.getBluetoothAddress());
   } finally {
     mutex.readLock().unlock();
   }
 }
 public boolean hasConnection(String address) {
   mutex.readLock().lock();
   try {
     // check also visibility graph
     return routingTable.search(localDevice.getBluetoothAddress(), address);
   } finally {
     mutex.readLock().unlock();
   }
 }
 public void removeConnection(String address) {
   mutex.writeLock().lock();
   try {
     if (connections.containsKey(address)) {
       ConnectionHandler handler = connections.get(address);
       connections.remove(address);
       routingTable.remove(localDevice.getBluetoothAddress(), address);
       handler.setStop(true);
     }
   } finally {
     mutex.writeLock().unlock();
   }
 }
  private SyndicateCore() throws BluetoothStateException {
    // initialize properties
    initProperties();
    Log("SynCore", "properties initialized");
    SYNDICATE_UUID = new UUID("04A6C7B", false);
    localDevice = LocalDevice.getLocalDevice();
    Log("SynCore", "local device initialized");

    mutex = new ReentrantReadWriteLock();
    connections = new HashMap<String, ConnectionHandler>();
    routingTable = new RoutingTable();
    routingTable.add(localDevice.getBluetoothAddress());
    lock = new ReentrantLock();
    master = false;
    in = new ConcurrentLinkedQueue<Packet>();
    history = new ConcurrentHashMap<String, String>();
  }
  public void handleDataPacket(Packet p) {
    // this packet is for this device
    if (p.getDestination().equals(localDevice.getBluetoothAddress())) {
      offer(p);
    } else {
      String nextHop = routingTable.nextHop(localDevice.getBluetoothAddress(), p.getDestination());

      if (nextHop != null) {
        Log("SynCore", "Packet from: " + p.getSource() + " routed to: " + nextHop);
        for (String n : connections.keySet()) {
          if (n.equals(nextHop)) {
            connections.get(n).offer(p);
          }
        }
      }
    }
  }
 public boolean send(String destination, byte[] data) {
   mutex.writeLock().lock();
   try {
     String nextHop = routingTable.nextHop(localDevice.getBluetoothAddress(), destination);
     if (nextHop != null) {
       Packet p =
           new Packet(Packet.DATA_PACKET, localDevice.getBluetoothAddress(), destination, data);
       ConnectionHandler handler = connections.get(nextHop);
       if (handler != null) {
         handler.offer(p);
         return true;
       }
     }
   } finally {
     mutex.writeLock().unlock();
   }
   return false;
 }
 public void acceptConnection(BtConnection connection, boolean server) {
   mutex.writeLock().lock();
   try {
     if (!hasConnection(connection.getRemoteDevice().getBluetoothAddress())
         && connections.size() < 2) {
       ConnectionHandler handler = new ConnectionHandler(connection);
       connections.put(handler.getBtAddress(), handler);
       handler.start();
       routingTable.add(localDevice.getBluetoothAddress(), handler.getBtAddress());
     } else {
       connection.close();
     }
   } catch (IOException e) {
     Log("SynCore.acceptConnection", e.getMessage());
   } finally {
     mutex.writeLock().unlock();
   }
 }