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();
   }
 }
 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;
 }
    @Override
    public void run() {
      serverThread.setStop(true);
      clientThread.setStop(true);

      for (String connection : connections.keySet()) {
        ConnectionHandler handler = connections.get(connection);
        handler.setStop(true);
        try {
          // wait for the thread to finish
          handler.join();
        } catch (InterruptedException e) {

        }
      }

      connections.clear();
    }
 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();
   }
 }