use of com.biglybt.core.dht.nat.DHTNATPuncherListener in project BiglyBT by BiglySoftware.
the class PairingManagerTunnelHandler method start.
private void start() {
synchronized (this) {
if (started) {
return;
}
started = true;
}
N_3072 = fromHex("FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08" + "8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B" + "302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9" + "A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6" + "49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8" + "FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" + "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C" + "180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718" + "3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D" + "04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D" + "B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226" + "1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" + "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC" + "E0FD108E 4B82D120 A93AD2CA FFFFFFFF FFFFFFFF");
G_3072 = BigInteger.valueOf(5);
try {
PluginInterface dht_pi = core.getPluginManager().getPluginInterfaceByClass(DHTPlugin.class);
if (dht_pi == null) {
throw (new Exception("DHT Plugin not found"));
}
DHTPlugin dht_plugin = (DHTPlugin) dht_pi.getPlugin();
if (!dht_plugin.isEnabled()) {
throw (new Exception("DHT Plugin is disabled"));
}
DHT[] dhts = dht_plugin.getDHTs();
List<DHTNATPuncher> punchers = new ArrayList<>();
for (DHT dht : dhts) {
int net = dht.getTransport().getNetwork();
if (net == DHT.NW_AZ_MAIN) {
DHTNATPuncher primary_puncher = dht.getNATPuncher();
if (primary_puncher != null) {
punchers.add(primary_puncher);
nat_punchers_ipv4.add(primary_puncher);
for (int i = 1; i <= 2; i++) {
DHTNATPuncher puncher = primary_puncher.getSecondaryPuncher();
punchers.add(puncher);
nat_punchers_ipv4.add(puncher);
}
}
} else if (net == DHT.NW_AZ_MAIN_V6) {
/*
* no point in this atm as we don't support v6 tunnels
DHTNATPuncher puncher = dht.getNATPuncher();
if ( puncher != null ){
punchers.add( puncher );
nat_punchers_ipv6.add( puncher );
puncher = puncher.getSecondaryPuncher();
punchers.add( puncher );
nat_punchers_ipv6.add( puncher );
}
*/
}
}
if (punchers.size() == 0) {
throw (new Exception("No suitable DHT instances available"));
}
for (DHTNATPuncher p : punchers) {
p.forceActive(true);
p.addListener(new DHTNATPuncherListener() {
@Override
public void rendezvousChanged(DHTTransportContact rendezvous) {
System.out.println("active: " + rendezvous.getString());
synchronized (PairingManagerTunnelHandler.this) {
if (update_event == null) {
update_event = SimpleTimer.addEvent("PMT:defer", SystemTime.getOffsetTime(15 * 1000), new TimerEventPerformer() {
@Override
public void perform(TimerEvent event) {
synchronized (PairingManagerTunnelHandler.this) {
update_event = null;
}
System.out.println(" updating");
manager.updateNeeded();
}
});
}
}
}
});
}
core.getNATTraverser().registerHandler(new NATTraversalHandler() {
private final Map<Long, Object[]> server_map = new LinkedHashMap<Long, Object[]>(10, 0.75f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry<Long, Object[]> eldest) {
return size() > 10;
}
};
@Override
public int getType() {
return (NATTraverser.TRAVERSE_REASON_PAIR_TUNNEL);
}
@Override
public String getName() {
return ("Pairing Tunnel");
}
@Override
public Map process(InetSocketAddress originator, Map data) {
if (SRP_VERIFIER == null || !active) {
return (null);
}
boolean good_request = false;
try {
Map result = new HashMap();
Long session = (Long) data.get("sid");
if (session == null) {
return (null);
}
InetAddress tunnel_originator;
try {
tunnel_originator = InetAddress.getByAddress((byte[]) data.get("origin"));
} catch (Throwable e) {
Debug.out("originator decode failed: " + data);
return (null);
}
System.out.println("PairManagerTunnelHander: incoming message - session=" + session + ", payload=" + data + " from " + tunnel_originator + " via " + originator);
SRP6Server server;
BigInteger B;
synchronized (server_map) {
Object[] entry = server_map.get(session);
if (entry == null) {
long diff = SystemTime.getMonotonousTime() - last_server_create_time;
if (diff < 5000) {
try {
long sleep = 5000 - diff;
System.out.println("Sleeping for " + sleep + " before starting srp");
Thread.sleep(sleep);
} catch (Throwable e) {
}
}
server = new SRP6Server();
server.init(N_3072, G_3072, SRP_VERIFIER, new SHA256Digest(), RandomUtils.SECURE_RANDOM);
B = server.generateServerCredentials();
server_map.put(session, new Object[] { server, B });
last_server_create_time = SystemTime.getMonotonousTime();
total_servers++;
} else {
server = (SRP6Server) entry[0];
B = (BigInteger) entry[1];
}
}
Long op = (Long) data.get("op");
if (op == 1) {
result.put("op", 2);
result.put("s", SRP_SALT);
result.put("b", B.toByteArray());
good_request = true;
if (data.containsKey("test")) {
manager.recordRequest("SRP Test", originator.getAddress().getHostAddress(), true);
}
} else if (op == 3) {
boolean log_error = true;
try {
long diff = SystemTime.getMonotonousTime() - last_server_agree_time;
if (diff < 5000) {
try {
long sleep = 5000 - diff;
System.out.println("Sleeping for " + sleep + " before completing srp");
Thread.sleep(sleep);
} catch (Throwable e) {
}
}
BigInteger A = new BigInteger((byte[]) data.get("a"));
BigInteger serverS = server.calculateSecret(A);
byte[] shared_secret = serverS.toByteArray();
Cipher decipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] key = new byte[16];
System.arraycopy(shared_secret, 0, key, 0, 16);
SecretKeySpec secret = new SecretKeySpec(key, "AES");
decipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec((byte[]) data.get("enc_iv")));
byte[] dec = decipher.doFinal((byte[]) data.get("enc_data"));
String json_str = new String(dec, "UTF-8");
if (!json_str.startsWith("{")) {
log_error = false;
throw (new Exception("decode failed"));
}
JSONObject dec_json = (JSONObject) JSONUtils.decodeJSON(json_str);
String tunnel_url = (String) dec_json.get("url");
String service_id = new String((byte[]) data.get("service"), "UTF-8");
String endpoint_url = (String) dec_json.get("endpoint");
boolean ok = createTunnel(tunnel_originator, session, service_id, secret, tunnel_url, endpoint_url);
result.put("op", 4);
result.put("status", ok ? "ok" : "failed");
good_request = true;
} catch (Throwable e) {
result.put("op", 4);
result.put("status", "failed");
if (e instanceof BadPaddingException || e instanceof IllegalBlockSizeException) {
log_error = false;
}
if (log_error) {
e.printStackTrace();
}
} finally {
last_server_agree_time = SystemTime.getMonotonousTime();
}
}
return (result);
} finally {
if (!good_request) {
manager.recordRequest("SRP", originator.getAddress().getHostAddress(), false);
}
}
}
});
SimpleTimer.addPeriodicEvent("pm:tunnel:stats", 30 * 1000, new TimerEventPerformer() {
@Override
public void perform(TimerEvent event) {
synchronized (tunnels) {
if (tunnels.size() > 0) {
System.out.println("PairTunnels: " + tunnels.size());
for (PairManagerTunnel t : tunnels.values()) {
System.out.println("\t" + t.getString());
}
}
}
}
});
} catch (Throwable e) {
Debug.out(e);
init_fail = Debug.getNestedExceptionMessage(e);
manager.updateSRPState();
}
}
use of com.biglybt.core.dht.nat.DHTNATPuncherListener in project BiglyBT by BiglySoftware.
the class DHTNATPuncherImpl method runRendezvousSupport.
protected void runRendezvousSupport() {
try {
DHTTransportContact latest_local;
DHTTransportContact latest_target;
try {
pub_mon.enter();
latest_local = rendezvous_local_contact;
latest_target = rendezvous_target;
} finally {
pub_mon.exit();
}
if (current_local != null || latest_local != null) {
if (current_local != latest_local) {
if (current_local != null) {
if (!is_secondary) {
log("Removing publish for " + current_local.getString() + " -> " + current_target.getString());
dht.remove(getPublishKey(current_local), "DHTNatPuncher: removal of publish", new DHTOperationListener() {
@Override
public void searching(DHTTransportContact contact, int level, int active_searches) {
}
@Override
public void found(DHTTransportContact contact, boolean is_closest) {
}
@Override
public boolean diversified(String desc) {
return (true);
}
@Override
public void read(DHTTransportContact contact, DHTTransportValue value) {
}
@Override
public void wrote(DHTTransportContact contact, DHTTransportValue value) {
}
@Override
public void complete(boolean timeout) {
}
});
}
}
if (latest_local != null) {
// only 2 attempts to start with
rendevzous_fail_count = RENDEZVOUS_PING_FAIL_LIMIT - 2;
if (!is_secondary) {
log("Adding publish for " + latest_local.getString() + " -> " + latest_target.getString());
final byte[] publish_key = getPublishKey(latest_local);
dht.put(publish_key, "NAT Traversal: rendezvous publish", encodePublishValue(latest_target), DHT.FLAG_SINGLE_VALUE, new DHTOperationListener() {
private final List<DHTTransportContact> written_to = new ArrayList<>();
@Override
public void searching(DHTTransportContact contact, int level, int active_searches) {
}
@Override
public void found(DHTTransportContact contact, boolean is_closest) {
}
@Override
public boolean diversified(String desc) {
return (true);
}
@Override
public void read(DHTTransportContact contact, DHTTransportValue value) {
}
@Override
public void wrote(DHTTransportContact contact, DHTTransportValue value) {
synchronized (written_to) {
written_to.add(contact);
}
}
@Override
public void complete(boolean timeout) {
synchronized (written_to) {
last_publish_key = publish_key;
last_write_set = written_to;
}
}
});
}
}
} else if (current_target != latest_target) {
// here current_local == latest_local and neither is null!
// target changed, update publish
// only 2 attempts to start with
rendevzous_fail_count = RENDEZVOUS_PING_FAIL_LIMIT - 2;
if (!is_secondary) {
log("Updating publish for " + latest_local.getString() + " -> " + latest_target.getString());
final byte[] publish_key = getPublishKey(latest_local);
dht.put(publish_key, "DHTNatPuncher: update publish", encodePublishValue(latest_target), DHT.FLAG_SINGLE_VALUE, new DHTOperationListener() {
private final List<DHTTransportContact> written_to = new ArrayList<>();
@Override
public void searching(DHTTransportContact contact, int level, int active_searches) {
}
@Override
public void found(DHTTransportContact contact, boolean is_closest) {
}
@Override
public boolean diversified(String desc) {
return (true);
}
@Override
public void read(DHTTransportContact contact, DHTTransportValue value) {
}
@Override
public void wrote(DHTTransportContact contact, DHTTransportValue value) {
synchronized (written_to) {
written_to.add(contact);
}
}
@Override
public void complete(boolean timeout) {
synchronized (written_to) {
last_publish_key = publish_key;
last_write_set = written_to;
}
}
});
}
}
}
current_local = latest_local;
current_target = latest_target;
if (current_target != null) {
long now = SystemTime.getMonotonousTime();
int bind_result = sendBind(current_target);
if (bind_result == RESP_OK) {
trace("Rendezvous:" + current_target.getString() + " OK");
rendevzous_fail_count = 0;
rendezvous_last_ok_time = now;
if (last_ok_rendezvous != current_target) {
last_ok_rendezvous = current_target;
log("Rendezvous " + latest_target.getString() + " operational");
for (DHTNATPuncherListener l : listeners) {
l.rendezvousChanged(current_target);
}
}
} else {
rendezvous_last_fail_time = now;
if (bind_result == RESP_NOT_OK) {
// denied access
rendevzous_fail_count = RENDEZVOUS_PING_FAIL_LIMIT;
} else {
rendevzous_fail_count++;
}
if (rendevzous_fail_count == RENDEZVOUS_PING_FAIL_LIMIT) {
rendezvousFailed(current_target, false);
}
}
}
} catch (Throwable e) {
log(e);
}
}
Aggregations