protected void receiveTunnelInbound(DHTTransportUDPContact originator, Map data) { log("Received tunnel inbound message from " + originator.getString()); try { punch_mon.enter(); for (int i = 0; i < oustanding_punches.size(); i++) { Object[] wait_data = (Object[]) oustanding_punches.get(i); DHTTransportContact wait_contact = (DHTTransportContact) wait_data[0]; if (originator.getAddress().getAddress().equals(wait_contact.getAddress().getAddress())) { wait_data[2] = new Integer(originator.getTransportAddress().getPort()); ((AESemaphore) wait_data[1]).release(); } } } finally { punch_mon.exit(); } }
public void setRendezvous(DHTTransportContact target, DHTTransportContact rendezvous) { explicit_rendezvous_map.put(target.getAddress(), rendezvous); if (target.getAddress().equals(dht.getTransport().getLocalContact().getAddress())) { publish(true); } }
protected void rendezvousFailed(DHTTransportContact current_target, boolean tidy) { log("Rendezvous " + (tidy ? "closed" : "failed") + ": " + current_target.getString()); try { pub_mon.enter(); failed_rendezvous.put(current_target.getAddress(), ""); } finally { pub_mon.exit(); } publish(true); }
public static String getString(DHTTransportContact contact) { if (logging_on) { return (contact.getString()); } else { return (""); } }
protected void receiveClose(DHTTransportUDPContact originator, Map request, Map response) { trace("received close request"); final DHTTransportContact current_target = rendezvous_target; if (current_target != null && Arrays.equals(current_target.getID(), originator.getID())) { new AEThread2("DHTNATPuncher:close", true) { public void run() { rendezvousFailed(current_target, true); } }.start(); } response.put("ok", new Long(1)); }
protected byte[] getPublishKey(DHTTransportContact contact) { byte[] id = contact.getID(); byte[] suffix = ":DHTNATPuncher".getBytes(); byte[] res = new byte[id.length + suffix.length]; System.arraycopy(id, 0, res, 0, id.length); System.arraycopy(suffix, 0, res, id.length, suffix.length); return (res); }
protected void findContacts() { DHTTransportContact[] reachables = dht.getTransport().getReachableContacts(); for (int i = 0; i < reachables.length; i++) { DHTTransportContact contact = reachables[i]; byte[] address = contact.getAddress().getAddress().getAddress(); if (tried_bloom == null || tried_bloom.getEntryCount() > 500) { tried_bloom = BloomFilterFactory.createAddOnly(4096); } if (!tried_bloom.contains(address)) { tried_bloom.add(address); synchronized (pending_contacts) { potentialPing ping = new potentialPing( contact, DHTNetworkPositionManager.estimateRTT( contact.getNetworkPositions(), dht.getTransport().getLocalContact().getNetworkPositions())); pending_contacts.add(0, ping); if (pending_contacts.size() > 60) { pending_contacts.removeLast(); } } } } }
protected boolean sendTunnelOutbound(DHTTransportContact target) { log("Sending tunnel outbound message to " + target.getString()); try { Map message = new HashMap(); message.put("type", new Long(RT_TUNNEL_OUTBOUND)); return (sendTunnelMessage(target, message)); } catch (Throwable e) { log(e); return (false); } }
protected byte[] encodeContact(DHTTransportContact contact) { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); contact.exportContact(dos); dos.close(); return (baos.toByteArray()); } catch (Throwable e) { log(e); return (null); } }
protected byte[] encodePublishValue(DHTTransportContact contact) { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); dos.writeByte(0); // version contact.exportContact(dos); dos.close(); return (baos.toByteArray()); } catch (Throwable e) { log(e); return (new byte[0]); } }
protected void updateRegistrationData(Map<String, Object> payload) { int puncher_num = 0; int num_registered = 0; for (DHTNATPuncher nat_ipv4 : nat_punchers_ipv4) { DHTTransportContact rend = nat_ipv4.getRendezvous(); DHTTransportContact lc = nat_ipv4.getLocalContact(); if (rend != null && lc != null) { puncher_num++; InetSocketAddress rend_address = rend.getTransportAddress(); num_registered++; payload.put( "rc_v4-" + puncher_num, rend_address.getAddress().getHostAddress() + ":" + rend_address.getPort()); if (puncher_num == 1) { payload.put( "rl_v4", lc.getExternalAddress().getAddress().getHostAddress() + ":" + lc.getAddress().getPort()); } } } puncher_num = 0; for (DHTNATPuncher nat_ipv6 : nat_punchers_ipv6) { DHTTransportContact rend = nat_ipv6.getRendezvous(); DHTTransportContact lc = nat_ipv6.getLocalContact(); if (rend != null && lc != null) { puncher_num++; InetSocketAddress rend_address = rend.getTransportAddress(); num_registered++; payload.put( "rc_v6-" + puncher_num, rend_address.getAddress().getHostAddress() + ":" + rend_address.getPort()); if (puncher_num == 1) { payload.put( "rl_v6", lc.getExternalAddress().getAddress().getHostAddress() + ":" + lc.getAddress().getPort()); } } } if (num_registered != last_punchers_registered) { last_punchers_registered = num_registered; manager.updateSRPState(); } }
protected void ping(pingInstanceSet ping_set, DHTTransportContact contact) { final pingInstance pi = new pingInstance(ping_set); outstanding++; try { contact.sendImmediatePing( new DHTTransportReplyHandlerAdapter() { public void pingReply(DHTTransportContact contact) { int rtt = getElapsed(); try { synchronized (activePing.this) { outstanding--; if (!running) { if (rtt < best_ping) { best_pingee = contact; best_ping = rtt; } if (outstanding == 0) { running = true; } } else { total_ok++; consec_fails = 0; } } Iterator it = listeners.iterator(); while (it.hasNext()) { try { ((DHTSpeedTesterContactListener) it.next()) .ping(activePing.this, getElapsed()); } catch (Throwable e) { Debug.printStackTrace(e); } } } finally { pi.setResult(activePing.this, rtt); } // System.out.println( " " + contact.getString() + ": " + getElapsed() + ", " + // contact.getVivaldiPosition().estimateRTT( // dht.getTransport().getLocalContact().getVivaldiPosition().getCoordinates())); } public void failed(DHTTransportContact contact, Throwable error) { try { synchronized (activePing.this) { outstanding--; if (!running) { if (outstanding == 0) { running = true; } } else { consec_fails++; total_fails++; if (consec_fails == 3) { dead = true; } else if (total_ok > 10 && total_fails > 0 && total_ok / total_fails < 1) { // failing too often dead = true; } else if (total_ok > 100) { total_ok = 0; total_fails = 0; } } } if (!dead) { Iterator it = listeners.iterator(); while (it.hasNext()) { try { ((DHTSpeedTesterContactListener) it.next()).pingFailed(activePing.this); } catch (Throwable e) { Debug.printStackTrace(e); } } } // System.out.println( " " + contact.getString() + ": failed" ); } finally { pi.setResult(activePing.this, -1); } } }, PING_TIMEOUT); } catch (Throwable e) { pi.setResult(this, -1); dead = true; outstanding--; Debug.printStackTrace(e); } }
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(); } } }
protected DHTTransportContact getRendezvous(String reason, DHTTransportContact target) { DHTTransportContact explicit = (DHTTransportContact) explicit_rendezvous_map.get(target.getAddress()); if (explicit != null) { return (explicit); } byte[] key = getPublishKey(target); final DHTTransportValue[] result_value = {null}; final Semaphore sem = plugin_interface.getUtilities().getSemaphore(); dht.get( key, reason + ": lookup for '" + target.getString() + "'", (byte) 0, 1, RENDEZVOUS_LOOKUP_TIMEOUT, false, true, new DHTOperationAdapter() { public void read(DHTTransportContact contact, DHTTransportValue value) { result_value[0] = value; sem.release(); } public void complete(boolean timeout) { sem.release(); } }); sem.reserve(); DHTTransportContact result = null; if (result_value[0] != null) { byte[] bytes = result_value[0].getValue(); try { ByteArrayInputStream bais = new ByteArrayInputStream(bytes); DataInputStream dis = new DataInputStream(bais); byte version = dis.readByte(); if (version != 0) { throw (new Exception("Unsupported rendezvous version '" + version + "'")); } result = dht.getTransport().importContact(dis); } catch (Throwable e) { log(e); } } log( "Lookup of rendezvous for " + target.getString() + " -> " + (result == null ? "None" : result.getString())); return (result); }
protected void receiveTunnelOutbound(DHTTransportContact originator, Map data) { log("Received tunnel outbound message from " + originator.getString()); }
protected void receiveConnect(DHTTransportContact rendezvous, Map request, Map response) { trace("received connect request"); boolean ok = false; // ensure that we've received this from our current rendezvous node DHTTransportContact rt = rendezvous_target; if (rt != null && rt.getAddress().equals(rendezvous.getAddress())) { final DHTTransportUDPContact target = decodeContact((byte[]) request.get("origin")); if (target != null) { int transport_port = 0; Long indirect_port = (Long) request.get("port"); if (indirect_port != null) { transport_port = indirect_port.intValue(); } if (transport_port != 0) { InetSocketAddress existing_address = target.getTransportAddress(); if (transport_port != existing_address.getPort()) { target.setTransportAddress( new InetSocketAddress(existing_address.getAddress(), transport_port)); } } Map originator_client_data = (Map) request.get("client_data"); boolean no_tunnel = false; if (originator_client_data == null) { originator_client_data = new HashMap(); } else { no_tunnel = originator_client_data.get("_notunnel") != null; } if (no_tunnel) { log("Received message from " + target.getString()); } else { log("Received connect request from " + target.getString()); // ping the origin a few times to try and establish a tunnel UTTimerEvent event = timer.addPeriodicEvent( 3000, new UTTimerEventPerformer() { private int pings = 1; public void perform(UTTimerEvent ev) { if (pings > 3) { ev.cancel(); return; } pings++; if (sendTunnelInbound(target)) { ev.cancel(); } } }); if (sendTunnelInbound(target)) { event.cancel(); } } Map client_data = adapter.getClientData(target.getTransportAddress(), originator_client_data); if (client_data == null) { client_data = new HashMap(); } response.put("client_data", client_data); ok = true; } else { log("Connect request: failed to decode target"); } } else { log("Connect request from invalid rendezvous: " + rendezvous.getString()); } response.put("ok", new Long(ok ? 1 : 0)); }