protected PRUDPPacket handleConnect(String client_ip_address, PRUDPPacketRequest request) { long conn_id = allocateConnectionId(client_ip_address); PRUDPPacket reply = new PRUDPPacketReplyConnect(request.getTransactionId(), conn_id); return (reply); }
public void runSupport() { byte[] input_buffer = new byte[request_dg.getLength()]; System.arraycopy(request_dg.getData(), 0, input_buffer, 0, input_buffer.length); int packet_data_length = input_buffer.length; String auth_user = null; byte[] auth_user_bytes = null; byte[] auth_hash = null; if (server.isTrackerPasswordEnabled()) { // auth detail should be attached to the packet. Auth details are 16 // bytes if (input_buffer.length < 17) { Logger.log( new LogEvent( LOGID, LogEvent.LT_WARNING, "TRTrackerServerProcessorUDP: " + "packet received but authorisation missing")); return; } packet_data_length -= 16; auth_user_bytes = new byte[8]; auth_hash = new byte[8]; System.arraycopy(input_buffer, packet_data_length, auth_user_bytes, 0, 8); int user_len = 0; while (user_len < 8 && auth_user_bytes[user_len] != 0) { user_len++; } auth_user = new String(auth_user_bytes, 0, user_len); System.arraycopy(input_buffer, packet_data_length + 8, auth_hash, 0, 8); } DataInputStream is = new DataInputStream(new ByteArrayInputStream(input_buffer, 0, packet_data_length)); try { String client_ip_address = request_dg.getAddress().getHostAddress(); PRUDPPacketRequest request = PRUDPPacketRequest.deserialiseRequest(null, is); Logger.log( new LogEvent( LOGID, "TRTrackerServerProcessorUDP: packet received: " + request.getString())); PRUDPPacket reply = null; TRTrackerServerTorrentImpl torrent = null; if (auth_user_bytes != null) { // user name is irrelevant as we only have one at the moment // <parg_home> so <new_packet> = <old_packet> + <user_padded_to_8_bytes> + <hash> // <parg_home> where <hash> = first 8 bytes of sha1(<old_packet> + <user_padded_to_8> + // sha1(pass)) // <XTF> Yes byte[] sha1_pw = null; if (server.hasExternalAuthorisation()) { try { URL resource = new URL("udp://" + server.getHost() + ":" + server.getPort() + "/"); sha1_pw = server.performExternalAuthorisation(resource, auth_user); } catch (MalformedURLException e) { Debug.printStackTrace(e); } if (sha1_pw == null) { Logger.log( new LogEvent( LOGID, LogEvent.LT_ERROR, "TRTrackerServerProcessorUDP: auth fails for user '" + auth_user + "'")); reply = new PRUDPPacketReplyError(request.getTransactionId(), "Access Denied"); } } else { sha1_pw = server.getPassword(); } // if we haven't already failed then check the PW if (reply == null) { SHA1Hasher hasher = new SHA1Hasher(); hasher.update(input_buffer, 0, packet_data_length); hasher.update(auth_user_bytes); hasher.update(sha1_pw); byte[] digest = hasher.getDigest(); for (int i = 0; i < auth_hash.length; i++) { if (auth_hash[i] != digest[i]) { Logger.log( new LogEvent( LOGID, LogEvent.LT_ERROR, "TRTrackerServerProcessorUDP: auth fails for user '" + auth_user + "'")); reply = new PRUDPPacketReplyError(request.getTransactionId(), "Access Denied"); break; } } } } int request_type = TRTrackerServerRequest.RT_UNKNOWN; if (reply == null) { if (server.isEnabled()) { try { int type = request.getAction(); if (type == PRUDPPacketTracker.ACT_REQUEST_CONNECT) { reply = handleConnect(client_ip_address, request); } else if (type == PRUDPPacketTracker.ACT_REQUEST_ANNOUNCE) { Object[] x = handleAnnounceAndScrape( client_ip_address, request, TRTrackerServerRequest.RT_ANNOUNCE); if (x == null) { throw (new Exception("Connection ID mismatch")); } reply = (PRUDPPacket) x[0]; torrent = (TRTrackerServerTorrentImpl) x[1]; request_type = TRTrackerServerRequest.RT_ANNOUNCE; } else if (type == PRUDPPacketTracker.ACT_REQUEST_SCRAPE) { Object[] x = handleAnnounceAndScrape( client_ip_address, request, TRTrackerServerRequest.RT_SCRAPE); if (x == null) { throw (new Exception("Connection ID mismatch")); } reply = (PRUDPPacket) x[0]; torrent = (TRTrackerServerTorrentImpl) x[1]; request_type = TRTrackerServerRequest.RT_SCRAPE; } else { reply = new PRUDPPacketReplyError(request.getTransactionId(), "unsupported action"); } } catch (Throwable e) { // e.printStackTrace(); String error = e.getMessage(); if (error == null) { error = e.toString(); } reply = new PRUDPPacketReplyError(request.getTransactionId(), error); } } else { System.out.println("UDP Tracker: replying 'disabled' to " + client_ip_address); reply = new PRUDPPacketReplyError(request.getTransactionId(), "UDP Tracker disabled"); } } if (reply != null) { InetAddress address = request_dg.getAddress(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream os = new DataOutputStream(baos); reply.serialise(os); byte[] output_buffer = baos.toByteArray(); DatagramPacket reply_packet = new DatagramPacket(output_buffer, output_buffer.length, address, request_dg.getPort()); socket.send(reply_packet); server.updateStats(request_type, torrent, input_buffer.length, output_buffer.length); } } catch (Throwable e) { Logger.log(new LogEvent(LOGID, "TRTrackerServerProcessorUDP: processing fails", e)); } finally { try { is.close(); } catch (Throwable e) { } } }
protected Object[] handleAnnounceAndScrape( String client_ip_address, PRUDPPacketRequest request, int request_type) throws Exception { if (!checkConnectionId(client_ip_address, request.getConnectionId())) { return (null); } List hashbytes = new ArrayList(); HashWrapper peer_id = null; int port = 0; String event = null; long uploaded = 0; long downloaded = 0; long left = 0; int num_want = -1; String key = null; if (request_type == TRTrackerServerRequest.RT_ANNOUNCE) { if (PRUDPPacketTracker.VERSION == 1) { PRUDPPacketRequestAnnounce announce = (PRUDPPacketRequestAnnounce) request; hashbytes.add(announce.getHash()); peer_id = new HashWrapper(announce.getPeerId()); port = announce.getPort(); int i_event = announce.getEvent(); switch (i_event) { case PRUDPPacketRequestAnnounce.EV_STARTED: { event = "started"; break; } case PRUDPPacketRequestAnnounce.EV_STOPPED: { event = "stopped"; break; } case PRUDPPacketRequestAnnounce.EV_COMPLETED: { event = "completed"; break; } } uploaded = announce.getUploaded(); downloaded = announce.getDownloaded(); left = announce.getLeft(); num_want = announce.getNumWant(); int i_ip = announce.getIPAddress(); if (i_ip != 0) { client_ip_address = PRHelpers.intToAddress(i_ip); } } else { PRUDPPacketRequestAnnounce2 announce = (PRUDPPacketRequestAnnounce2) request; hashbytes.add(announce.getHash()); peer_id = new HashWrapper(announce.getPeerId()); port = announce.getPort(); int i_event = announce.getEvent(); switch (i_event) { case PRUDPPacketRequestAnnounce.EV_STARTED: { event = "started"; break; } case PRUDPPacketRequestAnnounce.EV_STOPPED: { event = "stopped"; break; } case PRUDPPacketRequestAnnounce.EV_COMPLETED: { event = "completed"; break; } } uploaded = announce.getUploaded(); downloaded = announce.getDownloaded(); left = announce.getLeft(); num_want = announce.getNumWant(); int i_ip = announce.getIPAddress(); if (i_ip != 0) { client_ip_address = PRHelpers.intToAddress(i_ip); } key = "" + announce.getKey(); } } else { PRUDPPacketRequestScrape scrape = (PRUDPPacketRequestScrape) request; hashbytes.addAll(scrape.getHashes()); } Map[] root_out = new Map[1]; TRTrackerServerPeerImpl[] peer_out = new TRTrackerServerPeerImpl[1]; TRTrackerServerTorrentImpl torrent = processTrackerRequest( server, "", root_out, peer_out, request_type, (byte[][]) hashbytes.toArray(new byte[0][0]), null, null, peer_id, false, TRTrackerServerTorrentImpl.COMPACT_MODE_NONE, key, // currently no "no_peer_id" / "compact" in the packet and anyway they aren't // returned / key event, false, port, 0, 0, client_ip_address, client_ip_address, downloaded, uploaded, left, num_want, TRTrackerServerPeer.CRYPTO_NONE, (byte) 1, 0, null); Map root = root_out[0]; if (request_type == TRTrackerServerRequest.RT_ANNOUNCE) { if (PRUDPPacketTracker.VERSION == 1) { PRUDPPacketReplyAnnounce reply = new PRUDPPacketReplyAnnounce(request.getTransactionId()); reply.setInterval(((Long) root.get("interval")).intValue()); List peers = (List) root.get("peers"); int[] addresses = new int[peers.size()]; short[] ports = new short[addresses.length]; for (int i = 0; i < addresses.length; i++) { Map peer = (Map) peers.get(i); addresses[i] = PRHelpers.addressToInt(new String((byte[]) peer.get("ip"))); ports[i] = (short) ((Long) peer.get("port")).shortValue(); } reply.setPeers(addresses, ports); return (new Object[] {reply, torrent}); } else { PRUDPPacketReplyAnnounce2 reply = new PRUDPPacketReplyAnnounce2(request.getTransactionId()); reply.setInterval(((Long) root.get("interval")).intValue()); boolean local_scrape = client_ip_address.equals("127.0.0.1"); Map scrape_details = torrent.exportScrapeToMap("", client_ip_address, !local_scrape); int seeders = ((Long) scrape_details.get("complete")).intValue(); int leechers = ((Long) scrape_details.get("incomplete")).intValue(); reply.setLeechersSeeders(leechers, seeders); List peers = (List) root.get("peers"); int[] addresses = new int[peers.size()]; short[] ports = new short[addresses.length]; for (int i = 0; i < addresses.length; i++) { Map peer = (Map) peers.get(i); addresses[i] = PRHelpers.addressToInt(new String((byte[]) peer.get("ip"))); ports[i] = (short) ((Long) peer.get("port")).shortValue(); } reply.setPeers(addresses, ports); return (new Object[] {reply, torrent}); } } else { if (PRUDPPacketTracker.VERSION == 1) { PRUDPPacketReplyScrape reply = new PRUDPPacketReplyScrape(request.getTransactionId()); /* Long interval = (Long)root.get("interval"); if ( interval != null ){ reply.setInterval(interval.intValue()); } */ Map files = (Map) root.get("files"); byte[][] hashes = new byte[files.size()][]; int[] s_complete = new int[hashes.length]; int[] s_downloaded = new int[hashes.length]; int[] s_incomplete = new int[hashes.length]; Iterator it = files.keySet().iterator(); int pos = 0; while (it.hasNext()) { String hash_str = (String) it.next(); hashes[pos] = hash_str.getBytes(Constants.BYTE_ENCODING); Map details = (Map) files.get(hash_str); s_complete[pos] = ((Long) details.get("complete")).intValue(); s_incomplete[pos] = ((Long) details.get("incomplete")).intValue(); s_downloaded[pos] = ((Long) details.get("downloaded")).intValue(); pos++; } reply.setDetails(hashes, s_complete, s_downloaded, s_incomplete); return (new Object[] {reply, torrent}); } else { PRUDPPacketReplyScrape2 reply = new PRUDPPacketReplyScrape2(request.getTransactionId()); /* Long interval = (Long)root.get("interval"); if ( interval != null ){ reply.setInterval(interval.intValue()); } */ Map files = (Map) root.get("files"); int[] s_complete = new int[files.size()]; int[] s_downloaded = new int[s_complete.length]; int[] s_incomplete = new int[s_complete.length]; Iterator it = files.keySet().iterator(); int pos = 0; while (it.hasNext()) { String hash_str = (String) it.next(); Map details = (Map) files.get(hash_str); s_complete[pos] = ((Long) details.get("complete")).intValue(); s_incomplete[pos] = ((Long) details.get("incomplete")).intValue(); s_downloaded[pos] = ((Long) details.get("downloaded")).intValue(); pos++; } reply.setDetails(s_complete, s_downloaded, s_incomplete); return (new Object[] {reply, torrent}); } } }