Search in sources :

Example 1 with DHTNetworkPosition

use of com.biglybt.core.dht.netcoords.DHTNetworkPosition in project BiglyBT by BiglySoftware.

the class DHTUDPUtils method deserialiseVivaldi.

protected static void deserialiseVivaldi(DHTUDPPacketReply reply, DataInputStream is) throws IOException {
    DHTNetworkPosition[] nps;
    if (reply.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_GENERIC_NETPOS) {
        int entries = is.readByte() & 0xff;
        nps = new DHTNetworkPosition[entries];
        int skipped = 0;
        for (int i = 0; i < entries; i++) {
            byte type = is.readByte();
            byte size = is.readByte();
            DHTNetworkPosition np = DHTNetworkPositionManager.deserialise(reply.getAddress().getAddress(), type, is);
            if (np == null) {
                skipped++;
                for (int j = 0; j < size; j++) {
                    is.readByte();
                }
            } else {
                nps[i] = np;
            }
        }
        if (skipped > 0) {
            DHTNetworkPosition[] x = new DHTNetworkPosition[entries - skipped];
            int pos = 0;
            for (int i = 0; i < nps.length; i++) {
                if (nps[i] != null) {
                    x[pos++] = nps[i];
                }
            }
            nps = x;
        }
    } else {
        // dead code these days
        nps = new DHTNetworkPosition[] { DHTNetworkPositionManager.deserialise(reply.getAddress().getAddress(), DHTNetworkPosition.POSITION_TYPE_VIVALDI_V1, is) };
    }
    reply.setNetworkPositions(nps);
}
Also used : DHTNetworkPosition(com.biglybt.core.dht.netcoords.DHTNetworkPosition)

Example 2 with DHTNetworkPosition

use of com.biglybt.core.dht.netcoords.DHTNetworkPosition in project BiglyBT by BiglySoftware.

the class DHTUDPUtils method serialiseVivaldi.

protected static void serialiseVivaldi(DHTUDPPacketReply reply, DataOutputStream os) throws IOException {
    DHTNetworkPosition[] nps = reply.getNetworkPositions();
    if (reply.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_GENERIC_NETPOS) {
        boolean v1_found = false;
        for (int i = 0; i < nps.length; i++) {
            DHTNetworkPosition np = nps[i];
            if (np.getPositionType() == DHTNetworkPosition.POSITION_TYPE_VIVALDI_V1) {
                v1_found = true;
                break;
            }
        }
        if (!v1_found) {
            if (reply.getProtocolVersion() < DHTTransportUDP.PROTOCOL_VERSION_VIVALDI_OPTIONAL) {
                // need to add one in for backward compatability
                DHTNetworkPosition np = VivaldiPositionFactory.createPosition(Float.NaN);
                DHTNetworkPosition[] new_nps = new DHTNetworkPosition[nps.length + 1];
                System.arraycopy(nps, 0, new_nps, 0, nps.length);
                new_nps[nps.length] = np;
                nps = new_nps;
            }
        }
        os.writeByte((byte) nps.length);
        for (int i = 0; i < nps.length; i++) {
            DHTNetworkPosition np = nps[i];
            os.writeByte(np.getPositionType());
            os.writeByte(np.getSerialisedSize());
            np.serialise(os);
        }
    } else {
        for (int i = 0; i < nps.length; i++) {
            if (nps[i].getPositionType() == DHTNetworkPosition.POSITION_TYPE_VIVALDI_V1) {
                nps[i].serialise(os);
                return;
            }
        }
        Debug.out("Vivaldi V1 missing");
        throw (new IOException("Vivaldi V1 missing"));
    }
}
Also used : DHTNetworkPosition(com.biglybt.core.dht.netcoords.DHTNetworkPosition) IOException(java.io.IOException)

Example 3 with DHTNetworkPosition

use of com.biglybt.core.dht.netcoords.DHTNetworkPosition in project BiglyBT by BiglySoftware.

the class TRTrackerServerProcessorTCP method processRequest.

protected boolean processRequest(String input_header, String lowercase_input_header, String url_path, InetSocketAddress local_address, InetSocketAddress remote_address, boolean announce_and_scrape_only, boolean keep_alive, InputStream is, OutputStream os, AsyncController async) throws IOException {
    String str = url_path;
    int request_type = TRTrackerServerRequest.RT_UNKNOWN;
    boolean compact_enabled = server.isCompactEnabled();
    try {
        Map root = null;
        TRTrackerServerTorrentImpl specific_torrent = null;
        boolean gzip_reply = false;
        boolean xml_output = false;
        try {
            List<String> banned = TRTrackerServerImpl.banned_clients;
            if (!banned.isEmpty()) {
                int ua_pos = lowercase_input_header.indexOf("user-agent");
                if (ua_pos != -1) {
                    String user_agent = lowercase_input_header.substring(ua_pos + 10, lowercase_input_header.indexOf("\n", ua_pos)).trim().substring(1).trim();
                    for (String b : banned) {
                        if (user_agent.contains(b)) {
                            throw (new Exception(MSG_CLIENT_NOT_SUPPORTED));
                        }
                    }
                }
            }
            if (str.startsWith("/announce?")) {
                request_type = TRTrackerServerRequest.RT_ANNOUNCE;
                str = str.substring(10);
            } else if (str.startsWith("/scrape?")) {
                request_type = TRTrackerServerRequest.RT_SCRAPE;
                str = str.substring(8);
            } else if (str.equals("/scrape")) {
                request_type = TRTrackerServerRequest.RT_FULL_SCRAPE;
                str = "";
            } else if (str.startsWith("/query?")) {
                request_type = TRTrackerServerRequest.RT_QUERY;
                str = str.substring(7);
            } else {
                String redirect = TRTrackerServerImpl.redirect_on_not_found;
                if (announce_and_scrape_only) {
                    if (redirect.length() == 0) {
                        throw (new Exception("Tracker only supports announce and scrape functions"));
                    }
                } else {
                    setTaskState("external request");
                    disable_timeouts = true;
                    // check non-tracker authentication
                    String user = doAuthentication(remote_address, url_path, input_header, os, false);
                    if (user == null) {
                        return (false);
                    }
                    boolean[] ka = new boolean[] { keep_alive };
                    if (handleExternalRequest(local_address, remote_address, user, str, input_header, is, os, async, ka)) {
                        return (ka[0]);
                    }
                }
                if (redirect.length() > 0) {
                    os.write(("HTTP/1.1 301 Moved Permanently" + NL + "Location: " + redirect + NL + "Connection: close" + NL + "Content-Length: 0" + NL + NL).getBytes());
                } else {
                    os.write(("HTTP/1.1 404 Not Found" + NL + "Connection: close" + NL + "Content-Length: 0" + NL + NL).getBytes());
                }
                os.flush();
                // throw( new Exception( "Unsupported Request Type"));
                return (false);
            }
            if (doAuthentication(remote_address, url_path, input_header, os, true) == null) {
                return (false);
            }
            int enc_pos = lowercase_input_header.indexOf("accept-encoding:");
            if (enc_pos != -1) {
                int e_pos = input_header.indexOf(NL, enc_pos);
                if (e_pos != -1) {
                    if (enc_pos > 0) {
                        char c = lowercase_input_header.charAt(enc_pos - 1);
                        if (c != FF && c != ' ') {
                            enc_pos = -1;
                        }
                    }
                    if (enc_pos != -1) {
                        String accept_encoding = lowercase_input_header.substring(enc_pos + 16, e_pos);
                        gzip_reply = HTTPUtils.canGZIP(accept_encoding);
                    }
                }
            }
            setTaskState("decoding announce/scrape");
            int pos = 0;
            byte[] hash = null;
            List hash_list = null;
            String link = null;
            HashWrapper peer_id = null;
            int tcp_port = 0;
            String event = null;
            long uploaded = 0;
            long downloaded = 0;
            long left = 0;
            int num_want = -1;
            boolean no_peer_id = false;
            byte compact_mode = TRTrackerServerTorrentImpl.COMPACT_MODE_NONE;
            String key = null;
            byte crypto_level = TRTrackerServerPeer.CRYPTO_NONE;
            int crypto_port = 0;
            int udp_port = 0;
            int http_port = 0;
            int az_ver = 0;
            boolean stop_to_queue = false;
            String scrape_flags = null;
            int up_speed = 0;
            boolean hide = false;
            DHTNetworkPosition network_position = null;
            String real_ip_address = AddressUtils.getHostAddress(remote_address);
            String client_ip_address = real_ip_address;
            while (pos < str.length()) {
                int p1 = str.indexOf('&', pos);
                String token;
                if (p1 == -1) {
                    token = str.substring(pos);
                } else {
                    token = str.substring(pos, p1);
                    pos = p1 + 1;
                }
                int p2 = token.indexOf('=');
                if (p2 == -1) {
                    throw (new Exception("format invalid"));
                }
                String lhs = token.substring(0, p2).toLowerCase();
                String rhs = URLDecoder.decode(token.substring(p2 + 1), Constants.BYTE_ENCODING);
                if (lhs.equals("info_hash")) {
                    byte[] b = rhs.getBytes(Constants.BYTE_ENCODING);
                    if (hash == null) {
                        hash = b;
                    } else {
                        if (hash_list == null) {
                            hash_list = new ArrayList();
                            hash_list.add(hash);
                        }
                        hash_list.add(b);
                    }
                } else if (lhs.equals("peer_id")) {
                    peer_id = new HashWrapper(rhs.getBytes(Constants.BYTE_ENCODING));
                } else if (lhs.equals("no_peer_id")) {
                    no_peer_id = rhs.equals("1");
                } else if (lhs.equals("compact")) {
                    if (compact_enabled) {
                        if (rhs.equals("1") && compact_mode == TRTrackerServerTorrentImpl.COMPACT_MODE_NONE) {
                            compact_mode = TRTrackerServerTorrentImpl.COMPACT_MODE_NORMAL;
                        }
                    }
                } else if (lhs.equals("key")) {
                    if (server.isKeyEnabled()) {
                        key = rhs;
                    }
                } else if (lhs.equals("port")) {
                    tcp_port = Integer.parseInt(rhs);
                } else if (lhs.equals("event")) {
                    event = rhs;
                } else if (lhs.equals("ip")) {
                    if (!HostNameToIPResolver.isNonDNSName(rhs)) {
                        for (int i = 0; i < rhs.length(); i++) {
                            char c = rhs.charAt(i);
                            if (c != '.' && c != ':' && !Character.isDigit(c)) {
                                throw (new Exception("IP override address must be resolved by the client"));
                            }
                        }
                        try {
                            rhs = HostNameToIPResolver.syncResolve(rhs).getHostAddress();
                        } catch (UnknownHostException e) {
                            throw (new Exception("IP override address must be resolved by the client"));
                        }
                    } else if (AENetworkClassifier.categoriseAddress(client_ip_address) == AENetworkClassifier.AT_I2P) {
                    // ignore ip override as it is probably a full destination whereas the real originator is the .b32 equivalent
                    } else {
                        client_ip_address = rhs;
                    }
                } else if (lhs.equals("uploaded")) {
                    uploaded = Long.parseLong(rhs);
                } else if (lhs.equals("downloaded")) {
                    downloaded = Long.parseLong(rhs);
                } else if (lhs.equals("left")) {
                    left = Long.parseLong(rhs);
                } else if (lhs.equals("numwant")) {
                    num_want = Integer.parseInt(rhs);
                } else if (lhs.equals("azudp")) {
                    udp_port = Integer.parseInt(rhs);
                    if (compact_enabled) {
                        compact_mode = TRTrackerServerTorrentImpl.COMPACT_MODE_AZ;
                    }
                } else if (lhs.equals("azhttp")) {
                    http_port = Integer.parseInt(rhs);
                } else if (lhs.equals("azver")) {
                    az_ver = Integer.parseInt(rhs);
                } else if (lhs.equals("supportcrypto")) {
                    if (crypto_level == TRTrackerServerPeer.CRYPTO_NONE) {
                        crypto_level = TRTrackerServerPeer.CRYPTO_SUPPORTED;
                    }
                } else if (lhs.equals("requirecrypto")) {
                    crypto_level = TRTrackerServerPeer.CRYPTO_REQUIRED;
                } else if (lhs.equals("cryptoport")) {
                    crypto_port = Integer.parseInt(rhs);
                } else if (lhs.equals("azq")) {
                    stop_to_queue = true;
                } else if (lhs.equals("azsf")) {
                    scrape_flags = rhs;
                } else if (lhs.equals("link")) {
                    link = rhs;
                } else if (lhs.equals("outform")) {
                    if (rhs.equals("xml")) {
                        xml_output = true;
                    }
                } else if (lhs.equals("hide")) {
                    hide = Integer.parseInt(rhs) == 1;
                } else if (TRTrackerServerImpl.supportsExtensions()) {
                    if (lhs.equals("aznp")) {
                        try {
                            network_position = DHTNetworkPositionManager.deserialisePosition(remote_address.getAddress(), Base32.decode(rhs));
                        } catch (Throwable e) {
                        }
                    } else if (lhs.equals("azup")) {
                        up_speed = Integer.parseInt(rhs);
                    }
                }
                if (p1 == -1) {
                    break;
                }
            }
            if (hide) {
                tcp_port = 0;
                crypto_port = 0;
                http_port = 0;
                udp_port = 0;
            }
            if (crypto_level == TRTrackerServerPeer.CRYPTO_REQUIRED) {
                if (crypto_port != 0) {
                    tcp_port = crypto_port;
                }
            }
            byte[][] hashes = null;
            if (hash_list != null) {
                hashes = new byte[hash_list.size()][];
                hash_list.toArray(hashes);
            } else if (hash != null) {
                hashes = new byte[][] { hash };
            }
            if (compact_enabled) {
                if (xml_output) {
                    compact_mode = TRTrackerServerTorrentImpl.COMPACT_MODE_XML;
                } else if (az_ver >= 2) {
                    compact_mode = TRTrackerServerTorrentImpl.COMPACT_MODE_AZ_2;
                }
            }
            Map[] root_out = new Map[1];
            TRTrackerServerPeerImpl[] peer_out = new TRTrackerServerPeerImpl[1];
            specific_torrent = processTrackerRequest(server, str, root_out, peer_out, request_type, hashes, link, scrape_flags, peer_id, no_peer_id, compact_mode, key, event, stop_to_queue, tcp_port & 0xffff, udp_port & 0xffff, http_port & 0xffff, real_ip_address, client_ip_address, downloaded, uploaded, left, num_want, crypto_level, (byte) az_ver, up_speed, network_position);
            root = root_out[0];
            if (request_type == TRTrackerServerRequest.RT_SCRAPE) {
                if (lowercase_input_header.contains(lc_azureus_name)) {
                    root.put("aztracker", new Long(1));
                }
            }
            if (root.get("_data") == null) {
                TRTrackerServerPeer post_process_peer = peer_out[0];
                if (post_process_peer == null) {
                    post_process_peer = new lightweightPeer(client_ip_address, tcp_port, peer_id);
                }
                server.postProcess(post_process_peer, specific_torrent, request_type, str, root);
            }
        } catch (Exception e) {
            String warning_message = null;
            Map error_entries = null;
            if (e instanceof TRTrackerServerException) {
                TRTrackerServerException tr_excep = (TRTrackerServerException) e;
                int reason = tr_excep.getResponseCode();
                error_entries = tr_excep.getErrorEntries();
                if (reason != -1) {
                    String resp = "HTTP/1.1 " + reason + " " + tr_excep.getResponseText() + NL;
                    Map headers = tr_excep.getResponseHeaders();
                    Iterator it = headers.entrySet().iterator();
                    while (it.hasNext()) {
                        Map.Entry entry = (Map.Entry) it.next();
                        String key = (String) entry.getKey();
                        String value = (String) entry.getValue();
                        if (key.equalsIgnoreCase("connection")) {
                            if (!value.equalsIgnoreCase("close")) {
                                Debug.out("Ignoring 'Connection' header");
                                continue;
                            }
                        }
                        resp += key + ": " + value + NL;
                    }
                    resp += "Connection: close" + NL;
                    byte[] payload = null;
                    if (error_entries != null) {
                        payload = BEncoder.encode(error_entries);
                        resp += "Content-Length: " + payload.length + NL;
                    } else {
                        resp += "Content-Length: 0" + NL;
                    }
                    resp += NL;
                    os.write(resp.getBytes());
                    if (payload != null) {
                        os.write(payload);
                    }
                    os.flush();
                    return (false);
                }
                if (tr_excep.isUserMessage()) {
                    warning_message = tr_excep.getMessage();
                }
            } else if (e instanceof NullPointerException) {
                e.printStackTrace();
            }
            String message = e.getMessage();
            if (message == null || message.length() == 0) {
                // e.printStackTrace();
                message = e.toString();
            }
            root = new HashMap();
            root.put("failure reason", message);
            if (warning_message != null) {
                root.put("warning message", warning_message);
            }
            if (error_entries != null) {
                root.putAll(error_entries);
            }
        }
        setTaskState("writing response");
        byte[] data;
        byte[] header_start;
        if (xml_output) {
            StringBuilder xml = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            xml.append("<RESULT>");
            if (specific_torrent != null) {
                xml.append("<BTIH>");
                xml.append(ByteFormatter.encodeString(specific_torrent.getHash().getBytes()));
                xml.append("</BTIH>");
                xml.append(BEncoder.encodeToXML(root, true));
            }
            xml.append("</RESULT>");
            data = xml.toString().getBytes("UTF-8");
            header_start = HTTP_RESPONSE_XML_START;
        } else {
            // cache both plain and gzip encoded data for possible reuse
            data = (byte[]) root.get("_data");
            if (data == null) {
                data = BEncoder.encode(root);
                if (data.length > 1000000) {
                    File dump = new File("bdecoder.dump");
                    synchronized (TRTrackerServerProcessorTCP.class) {
                        try {
                            Debug.out("Output is too large, saving diagnostics to " + dump.toString());
                            PrintWriter pw = new PrintWriter(new FileWriter(dump));
                            BDecoder.print(pw, root);
                            pw.close();
                        } catch (Throwable e) {
                        }
                    }
                }
                root.put("_data", data);
            }
            header_start = HTTP_RESPONSE_START;
        }
        if (gzip_reply) {
            byte[] gzip_data = (byte[]) root.get("_gzipdata");
            if (gzip_data == null) {
                ByteArrayOutputStream tos = new ByteArrayOutputStream(data.length);
                GZIPOutputStream gos = new GZIPOutputStream(tos);
                gos.write(data);
                gos.close();
                gzip_data = tos.toByteArray();
                root.put("_gzipdata", gzip_data);
            }
            data = gzip_data;
        }
        // System.out.println( "TRTrackerServerProcessor::reply: sending " + new String(data));
        // write the response
        setTaskState("writing header");
        os.write(header_start);
        byte[] length_bytes = String.valueOf(data.length).getBytes();
        os.write(length_bytes);
        int header_len = header_start.length + length_bytes.length;
        setTaskState("writing content");
        if (gzip_reply) {
            os.write(HTTP_RESPONSE_END_GZIP);
            header_len += HTTP_RESPONSE_END_GZIP.length;
        } else {
            os.write(HTTP_RESPONSE_END_NOGZIP);
            header_len += HTTP_RESPONSE_END_NOGZIP.length;
        }
        os.write(data);
        server.updateStats(request_type, specific_torrent, input_header.length(), header_len + data.length);
    } finally {
        setTaskState("final os flush");
        os.flush();
    }
    return (false);
}
Also used : TRTrackerServerTorrentImpl(com.biglybt.core.tracker.server.impl.TRTrackerServerTorrentImpl) TRTrackerServerException(com.biglybt.core.tracker.server.TRTrackerServerException) DHTNetworkPosition(com.biglybt.core.dht.netcoords.DHTNetworkPosition) GZIPOutputStream(java.util.zip.GZIPOutputStream) TRTrackerServerPeer(com.biglybt.core.tracker.server.TRTrackerServerPeer) TRTrackerServerPeerImpl(com.biglybt.core.tracker.server.impl.TRTrackerServerPeerImpl) TRTrackerServerException(com.biglybt.core.tracker.server.TRTrackerServerException)

Example 4 with DHTNetworkPosition

use of com.biglybt.core.dht.netcoords.DHTNetworkPosition in project BiglyBT by BiglySoftware.

the class Show method showDHTStats.

protected void showDHTStats(ConsoleInput ci) {
    try {
        PluginInterface def = ci.core.getPluginManager().getDefaultPluginInterface();
        PluginInterface dht_pi = def.getPluginManager().getPluginInterfaceByClass(DHTPlugin.class);
        if (dht_pi == null) {
            ci.out.println("\tDHT isn't present");
            return;
        }
        DHTPlugin dht_plugin = (DHTPlugin) dht_pi.getPlugin();
        if (dht_plugin.getStatus() != DHTPlugin.STATUS_RUNNING) {
            ci.out.println("\tDHT isn't running yet (disabled or initialising)");
            return;
        }
        DHT[] dhts = dht_plugin.getDHTs();
        for (int i = 0; i < dhts.length; i++) {
            if (i > 0) {
                ci.out.println("");
            }
            DHT dht = dhts[i];
            DHTTransport transport = dht.getTransport();
            DHTTransportStats t_stats = transport.getStats();
            DHTDBStats d_stats = dht.getDataBase().getStats();
            DHTControlStats c_stats = dht.getControl().getStats();
            DHTRouterStats r_stats = dht.getRouter().getStats();
            long[] rs = r_stats.getStats();
            DHTNetworkPosition[] nps = transport.getLocalContact().getNetworkPositions();
            String np_str = "";
            for (int j = 0; j < nps.length; j++) {
                np_str += (j == 0 ? "" : ",") + nps[j];
            }
            ci.out.println("DHT:ip=" + transport.getLocalContact().getAddress() + ",net=" + transport.getNetwork() + ",prot=V" + transport.getProtocolVersion() + ",np=" + np_str + ",sleeping=" + dht.isSleeping());
            ci.out.println("Router" + ":nodes=" + rs[DHTRouterStats.ST_NODES] + ",leaves=" + rs[DHTRouterStats.ST_LEAVES] + ",contacts=" + rs[DHTRouterStats.ST_CONTACTS] + ",replacement=" + rs[DHTRouterStats.ST_REPLACEMENTS] + ",live=" + rs[DHTRouterStats.ST_CONTACTS_LIVE] + ",unknown=" + rs[DHTRouterStats.ST_CONTACTS_UNKNOWN] + ",failing=" + rs[DHTRouterStats.ST_CONTACTS_DEAD]);
            ci.out.println("Transport" + ":" + t_stats.getString());
            int[] dbv_details = d_stats.getValueDetails();
            ci.out.println("Control:dht=" + c_stats.getEstimatedDHTSize() + ", Database:keys=" + d_stats.getKeyCount() + ",vals=" + dbv_details[DHTDBStats.VD_VALUE_COUNT] + ",loc=" + dbv_details[DHTDBStats.VD_LOCAL_SIZE] + ",dir=" + dbv_details[DHTDBStats.VD_DIRECT_SIZE] + ",ind=" + dbv_details[DHTDBStats.VD_INDIRECT_SIZE] + ",div_f=" + dbv_details[DHTDBStats.VD_DIV_FREQ] + ",div_s=" + dbv_details[DHTDBStats.VD_DIV_SIZE]);
            dht.getRouter().print();
        }
    } catch (Throwable e) {
        e.printStackTrace(ci.out);
    }
}
Also used : DHTDBStats(com.biglybt.core.dht.db.DHTDBStats) PluginInterface(com.biglybt.pif.PluginInterface) DHT(com.biglybt.core.dht.DHT) DHTNetworkPosition(com.biglybt.core.dht.netcoords.DHTNetworkPosition) DHTPlugin(com.biglybt.plugin.dht.DHTPlugin) DHTRouterStats(com.biglybt.core.dht.router.DHTRouterStats) DHTControlStats(com.biglybt.core.dht.control.DHTControlStats)

Example 5 with DHTNetworkPosition

use of com.biglybt.core.dht.netcoords.DHTNetworkPosition in project BiglyBT by BiglySoftware.

the class TRTrackerBTAnnouncerImpl method constructUrl.

public URL constructUrl(String evt, URL _url) throws Exception {
    String url = _url.toString();
    StringBuffer request = new StringBuffer(url);
    // if url already has a query component then just append our parameters on the end
    if (url.indexOf('?') != -1) {
        request.append('&');
    } else {
        request.append('?');
    }
    // the client-id stuff RELIES on info_hash being the FIRST parameter added by
    // us to the URL, so don't change it!
    request.append(info_hash);
    request.append(tracker_peer_id_str);
    String port_details = announce_data_provider.getCryptoLevel() == NetworkManager.CRYPTO_OVERRIDE_REQUIRED ? TRTrackerUtils.getPortsForURLFullCrypto() : TRTrackerUtils.getPortsForURL();
    request.append(port_details);
    request.append("&uploaded=").append(announce_data_provider.getTotalSent());
    request.append("&downloaded=").append(announce_data_provider.getTotalReceived());
    if (Constants.DOWNLOAD_SOURCES_PRETEND_COMPLETE) {
        request.append("&left=0");
    } else {
        request.append("&left=").append(announce_data_provider.getRemaining());
    }
    // 3017: added at request of tracker admins who want to be able to monitor swarm poisoning
    request.append("&corrupt=").append(announce_data_provider.getFailedHashCheck());
    // TrackerID extension
    if (tracker_id.length() > 0) {
        request.append("&trackerid=").append(tracker_id);
    }
    if (evt.length() != 0) {
        request.append("&event=").append(evt);
    }
    boolean stopped = evt.equals("stopped");
    if (stopped) {
        request.append("&numwant=0");
        if (stopped_for_queue) {
            request.append("&azq=1");
        }
    } else {
        // calculate how many peers we should ask for
        int numwant = Math.min(calculateNumWant(), userMaxNumwant);
        request.append("&numwant=").append(numwant);
    // no_peer_id has been made obsolete by 'compact'
    }
    // actually, leave this in, ask PARG why!
    request.append("&no_peer_id=1");
    String tracker_network = AENetworkClassifier.categoriseAddress(_url.getHost());
    // latest space saving measure, a compact return type where peers are returned
    // as 6 byte entries in a single byte[] (4 bytes ip, 2 byte port)
    // leave this as always supplied, ask PARG why
    request.append("&compact=1");
    // any explicit override takes precedence over any implicit override added
    // when hosting torrents
    String explicit_ips = COConfigurationManager.getStringParameter("Override Ip", "");
    String ip = null;
    // make sure this tracker network is enabled
    boolean network_ok = false;
    boolean normal_network_ok = false;
    if (peer_networks == null) {
        network_ok = true;
        normal_network_ok = true;
    } else {
        for (int i = 0; i < peer_networks.length; i++) {
            if (peer_networks[i] == AENetworkClassifier.AT_PUBLIC) {
                normal_network_ok = true;
            }
            if (peer_networks[i] == tracker_network) {
                network_ok = true;
            }
        }
    }
    if (!network_ok) {
        throw (new Exception("Network not enabled for url '" + _url + "'"));
    }
    String normal_explicit = null;
    if (explicit_ips.length() > 0) {
        // gotta select an appropriate override based on network type
        StringTokenizer tok = new StringTokenizer(explicit_ips, ";");
        while (tok.hasMoreTokens()) {
            String this_address = tok.nextToken().trim();
            if (this_address.length() > 0) {
                String cat = AENetworkClassifier.categoriseAddress(this_address);
                if (cat == AENetworkClassifier.AT_PUBLIC) {
                    normal_explicit = this_address;
                }
                if (tracker_network == cat) {
                    ip = this_address;
                    break;
                }
            }
        }
    }
    if (ip == null) {
        if (normal_network_ok && normal_explicit != null) {
            ip = normal_explicit;
        } else {
            if (ip_override != null && !TorrentUtils.isDecentralised(ip_override)) {
                ip = ip_override;
            }
        }
    }
    if (ip != null) {
        if (tracker_network == AENetworkClassifier.AT_PUBLIC) {
            try {
                ip = PRHelpers.DNSToIPAddress(ip);
            } catch (UnknownHostException e) {
                if (Logger.isEnabled())
                    Logger.log(new LogEvent(torrent, LOGID, LogEvent.LT_ERROR, "IP Override host resolution of '" + ip + "' fails, using unresolved address"));
            }
        }
        request.append("&ip=").append(ip);
    }
    if (COConfigurationManager.getBooleanParameter("Tracker Key Enable Client", true)) {
        request.append("&key=").append(helper.getTrackerKey());
    }
    String ext = announce_data_provider.getExtensions();
    if (ext != null) {
        while (ext.startsWith("&")) {
            ext = ext.substring(1);
        }
        request.append("&");
        request.append(ext);
    }
    request.append("&azver=" + TRTrackerAnnouncer.AZ_TRACKER_VERSION_CURRENT);
    if (az_tracker && !stopped) {
        int up = announce_data_provider.getUploadSpeedKBSec(evt.equals("started"));
        if (up > 0) {
            request.append("&azup=").append(up);
        }
        String as = NetworkAdmin.getSingleton().getCurrentASN().getAS();
        if (as.length() > 0) {
            request.append("&azas=").append(URLEncoder.encode(as, "UTF8"));
        }
        DHTNetworkPosition best_position = DHTNetworkPositionManager.getBestLocalPosition();
        if (best_position != null) {
            try {
                byte[] bytes = DHTNetworkPositionManager.serialisePosition(best_position);
                request.append("&aznp=").append(Base32.encode(bytes));
            } catch (Throwable e) {
                Debug.printStackTrace(e);
            }
        }
    }
    if (tracker_network == AENetworkClassifier.AT_I2P) {
        String temp = request.toString();
        int pos = temp.indexOf('?');
        String head = temp.substring(0, pos);
        String tail = temp.substring(pos + 1);
        String[] bits = tail.split("&");
        Map<String, String> map = new HashMap<>();
        for (String bit : bits) {
            String[] arg = bit.split("=");
            map.put(arg[0], arg[1]);
        }
        tail = "";
        for (String str : new String[] { "info_hash", "peer_id", "port", "ip", "uploaded", "downloaded", "left", "compact", "event", "numwant" }) {
            String val = map.get(str);
            if (val != null) {
                tail += (tail.length() == 0 ? "" : "&") + str + "=" + map.get(str);
            }
        }
        request = new StringBuffer(head + "?" + tail);
    }
    return new URL(request.toString());
}
Also used : LogEvent(com.biglybt.core.logging.LogEvent) ClientIDException(com.biglybt.pif.clientid.ClientIDException) TOTorrentException(com.biglybt.core.torrent.TOTorrentException) IOException(java.io.IOException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) DHTNetworkPosition(com.biglybt.core.dht.netcoords.DHTNetworkPosition)

Aggregations

DHTNetworkPosition (com.biglybt.core.dht.netcoords.DHTNetworkPosition)8 IOException (java.io.IOException)2 DHT (com.biglybt.core.dht.DHT)1 DHTControlContact (com.biglybt.core.dht.control.DHTControlContact)1 DHTControlStats (com.biglybt.core.dht.control.DHTControlStats)1 DHTDBStats (com.biglybt.core.dht.db.DHTDBStats)1 DHTRouterStats (com.biglybt.core.dht.router.DHTRouterStats)1 LogEvent (com.biglybt.core.logging.LogEvent)1 TOTorrentException (com.biglybt.core.torrent.TOTorrentException)1 TRTrackerServerException (com.biglybt.core.tracker.server.TRTrackerServerException)1 TRTrackerServerPeer (com.biglybt.core.tracker.server.TRTrackerServerPeer)1 TRTrackerServerPeerImpl (com.biglybt.core.tracker.server.impl.TRTrackerServerPeerImpl)1 TRTrackerServerTorrentImpl (com.biglybt.core.tracker.server.impl.TRTrackerServerTorrentImpl)1 PluginInterface (com.biglybt.pif.PluginInterface)1 ClientIDException (com.biglybt.pif.clientid.ClientIDException)1 DHTPlugin (com.biglybt.plugin.dht.DHTPlugin)1 UnsupportedEncodingException (java.io.UnsupportedEncodingException)1 GZIPOutputStream (java.util.zip.GZIPOutputStream)1 Color (org.eclipse.swt.graphics.Color)1 GC (org.eclipse.swt.graphics.GC)1