protected void publishSupport() { DHTTransport transport = dht.getTransport(); if (TESTING || !transport.isReachable()) { DHTTransportContact local_contact = transport.getLocalContact(); // see if the rendezvous has failed and therefore we are required to find a new one boolean force = rendezvous_target != null && failed_rendezvous.containsKey(rendezvous_target.getAddress()); if (rendezvous_local_contact != null && !force) { if (local_contact.getAddress().equals(rendezvous_local_contact.getAddress())) { // already running for the current local contact return; } } DHTTransportContact explicit = (DHTTransportContact) explicit_rendezvous_map.get(local_contact.getAddress()); if (explicit != null) { try { pub_mon.enter(); rendezvous_local_contact = local_contact; rendezvous_target = explicit; runRendezvous(); } finally { pub_mon.exit(); } } else { final DHTTransportContact[] new_rendezvous_target = {null}; DHTTransportContact[] reachables = dht.getTransport().getReachableContacts(); int reachables_tried = 0; int reachables_skipped = 0; final Semaphore sem = plugin_interface.getUtilities().getSemaphore(); for (int i = 0; i < reachables.length; i++) { DHTTransportContact contact = reachables[i]; try { pub_mon.enter(); // see if we've found a good one yet if (new_rendezvous_target[0] != null) { break; } // skip any known bad ones if (failed_rendezvous.containsKey(contact.getAddress())) { reachables_skipped++; sem.release(); continue; } } finally { pub_mon.exit(); } if (i > 0) { try { Thread.sleep(1000); } catch (Throwable e) { } } reachables_tried++; contact.sendPing( new DHTTransportReplyHandlerAdapter() { public void pingReply(DHTTransportContact ok_contact) { trace("Punch:" + ok_contact.getString() + " OK"); try { pub_mon.enter(); if (new_rendezvous_target[0] == null) { new_rendezvous_target[0] = ok_contact; } } finally { pub_mon.exit(); sem.release(); } } public void failed(DHTTransportContact failed_contact, Throwable e) { try { trace("Punch:" + failed_contact.getString() + " Failed"); } finally { sem.release(); } } }); } for (int i = 0; i < reachables.length; i++) { sem.reserve(); try { pub_mon.enter(); if (new_rendezvous_target[0] != null) { rendezvous_target = new_rendezvous_target[0]; rendezvous_local_contact = local_contact; log( "Rendezvous found: " + rendezvous_local_contact.getString() + " -> " + rendezvous_target.getString()); runRendezvous(); break; } } finally { pub_mon.exit(); } } if (new_rendezvous_target[0] == null) { log( "No rendezvous found: candidates=" + reachables.length + ",tried=" + reachables_tried + ",skipped=" + reachables_skipped); try { pub_mon.enter(); rendezvous_local_contact = null; rendezvous_target = null; } finally { pub_mon.exit(); } } } } else { try { pub_mon.enter(); rendezvous_local_contact = null; rendezvous_target = null; } finally { pub_mon.exit(); } } }
public void start() { if (started) { return; } started = true; DHTTransport transport = dht.getTransport(); transport.addListener( new DHTTransportListener() { public void localContactChanged(DHTTransportContact local_contact) { publish(false); } public void currentAddress(String address) {} public void reachabilityChanged(boolean reacheable) { publish(false); } }); transport.registerTransferHandler( transfer_handler_key, new DHTTransportTransferHandler() { public String getName() { return ("NAT Traversal"); } public byte[] handleRead(DHTTransportContact originator, byte[] key) { return (null); } public byte[] handleWrite(DHTTransportContact originator, byte[] key, byte[] value) { return (receiveRequest((DHTTransportUDPContact) originator, value)); } }); timer.addPeriodicEvent( REPUBLISH_TIME_MIN, new UTTimerEventPerformer() { public void perform(UTTimerEvent event) { publish(false); } }); timer.addPeriodicEvent( RENDEZVOUS_SERVER_TIMEOUT / 2, new UTTimerEventPerformer() { public void perform(UTTimerEvent event) { long now = plugin_interface.getUtilities().getCurrentSystemTime(); try { server_mon.enter(); Iterator it = rendezvous_bindings.values().iterator(); while (it.hasNext()) { Object[] entry = (Object[]) it.next(); long time = ((Long) entry[1]).longValue(); boolean removed = false; if (time > now) { // clock change, easiest approach is to remove it it.remove(); removed = true; } else if (now - time > RENDEZVOUS_SERVER_TIMEOUT) { // timeout it.remove(); removed = true; } if (removed) { log( "Rendezvous " + ((DHTTransportContact) entry[0]).getString() + " removed due to inactivity"); } } } finally { server_mon.exit(); } } }); publish(false); }