From 32fc8fa1ece71e5570f57ec2c33847a09a1b9d69 Mon Sep 17 00:00:00 2001 From: administrador Date: Thu, 5 May 2022 16:08:23 -0300 Subject: [PATCH] Connect Finish, init cicly life reciver/uploader --- netinst.torrent | Bin 0 -> 30786 bytes sett.torrent | 1 + src/main/java/GivenTools/TorrentInfo.java | 9 +- src/main/java/org/voyager/torrent/Main.java | 13 +- .../voyager/torrent/client/ClientTorrent.java | 116 +++++++- .../voyager/torrent/client/model/Peer.java | 262 ++++++++++++++++++ .../org/voyager/torrent/util/BinaryUtil.java | 41 +++ .../org/voyager/torrent/util/HttpUtil.java | 61 ++++ .../voyager/torrent/util/ReaderBencode.java | 67 +++++ target/classes/org/voyager/torrent/Main.class | Bin 525 -> 770 bytes .../torrent/client/ClientTorrent.class | Bin 1110 -> 5447 bytes workspace.torrent | 2 + 12 files changed, 563 insertions(+), 9 deletions(-) create mode 100644 netinst.torrent create mode 100644 sett.torrent create mode 100644 src/main/java/org/voyager/torrent/client/model/Peer.java create mode 100644 src/main/java/org/voyager/torrent/util/BinaryUtil.java create mode 100644 src/main/java/org/voyager/torrent/util/HttpUtil.java create mode 100644 src/main/java/org/voyager/torrent/util/ReaderBencode.java create mode 100644 workspace.torrent diff --git a/netinst.torrent b/netinst.torrent new file mode 100644 index 0000000000000000000000000000000000000000..d67a89938816be89d81f998985dadade8f48b8cf GIT binary patch literal 30786 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
wxCh+)^9H|W3KN*jKl-!U518lUAiR78?8QoA83 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 fKJ parameters = new HashMap(); + parameters.put("info_hash",info_hash); + parameters.put("peer_id", peerId); // identify par + parameters.put("uploaded", "0"); + parameters.put("port", "-1"); // port connect + parameters.put("downloaded", "0"); + parameters.put("left", torrent.file_length+""); + System.out.println(torrent.announce_url); + + URL url_announce = new URL(torrent.announce_url+"?"+HttpUtil.getParamsString(parameters)); + + // get data for connect pars + HttpURLConnection con = (HttpURLConnection) url_announce.openConnection(); + con.setRequestMethod("GET"); + + con.connect(); + + // read response + StringBuffer res = BinaryUtil.inputStreamReaderToStringBuffer( new InputStreamReader(con.getInputStream()) ); + List listPeers = new ArrayList(); + System.out.println(res); + + Map map = ReaderBencode.bencodeToMap(res); + + int interval = (Integer) map.get( BinaryUtil.stringToByteBuffer("interval") ); + System.out.println( interval ); + + List> peersList = (List>) map.get(BinaryUtil.stringToByteBuffer("peers")); + + for (Map rawPeer : peersList) { + + int peerPort = ((Integer) rawPeer.get(BinaryUtil.stringToByteBuffer("port"))).intValue(); + + String ip = null; + try { + ip = new String(((ByteBuffer) rawPeer.get(BinaryUtil.stringToByteBuffer("ip"))).array(), + "ASCII"); + } catch (UnsupportedEncodingException e) { + System.out.println("Unable to parse encoding"); + continue; + } + //System.out.println("host: "+ip+"\t port: "+peerPort); + + listPeers.add( new Peer( ip, peerPort, peerIdBinary, this) ); + } + + for(Peer peer : listPeers.subList(0, 1)) { + Thread thread = new Thread(peer); + System.out.println(peer); + thread.start(); + } + + + } catch (MalformedURLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + public boolean addTorentFile(String arquivo){ + return addTorentFile(new File(arquivo)); + } + public boolean addTorentFile(File arquivo){ + this.torrent = ReaderBencode.parseTorrentFile(arquivo); + if(this.torrent == null)return false; + else return true; + } + } diff --git a/src/main/java/org/voyager/torrent/client/model/Peer.java b/src/main/java/org/voyager/torrent/client/model/Peer.java new file mode 100644 index 0000000..bffd718 --- /dev/null +++ b/src/main/java/org/voyager/torrent/client/model/Peer.java @@ -0,0 +1,262 @@ +package org.voyager.torrent.client.model; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; +import java.util.Arrays; + +import org.voyager.torrent.client.ClientTorrent; +import org.voyager.torrent.util.BinaryUtil; + +public class Peer implements Runnable{ + + // Info + private String host; + private int port; + private byte[] peer_id; + private ClientTorrent client; + private byte[] infoHash; + + // Codigo de menssagem + public static final byte MsgChoke = 0; + public static final byte MsgUnchoke = 1; + public static final byte MsgInterested = 2; + public static final byte MsgNotInterested = 3; + public static final byte MsgHave = 4; + public static final byte MsgBitfield = 5; + public static final byte MsgRequest = 6; + public static final byte MsgPiece = 7; + public static final byte MsgCancel = 8; + public static final byte[] Protocol = BinaryUtil.stringToByteBuffer("BitTorrent protocol").array(); + + // state + private Socket socket = null; + private InputStream in; + private OutputStream out; + public boolean isConnected = false; // CONNECT SOCKET + public boolean hasHandshake = false; // Connect Socket and shake Hands + + + public Peer(String host, int port, byte[] peer_id, ClientTorrent client) { + this.host = host; + this.port = port; + this.peer_id = peer_id; + this.client = client; + this.infoHash = client.torrent.info_hash.array(); + } + + public void run() { + + // open connect verify + if(!this.isConnected)this.isConnected = connect(); + + // Handshake verify + if(this.isConnected && !this.hasHandshake)this.hasHandshake = shakeHands(); + + // verify + if(!this.hasHandshake || !this.isConnected) throw new RuntimeException("Connect fail"); + else { + // Cicly Life + while (this.socket != null && !this.socket.isClosed()) { + //read length buffer + DataInputStream dataInput = new DataInputStream(this.in); + + try { + // size messagem + int length = dataInput.readInt(); + // 0 = keep alive (mantenha vivo) + if(length == 0)continue; + + + + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + + + } + + + + } + } + + private boolean shakeHands() { + + boolean hasHandshake = false; + + try { + + DataOutputStream os = new DataOutputStream(this.out); + DataInputStream is = new DataInputStream(this.in); + + if (is == null || os == null) { + return false; + } + + // send handshake + os.write(this.genHandshake()); + os.flush(); + + // response for peer + byte[] response = new byte[68]; + + + this.socket.setSoTimeout(10000); + is.readFully(response); + this.socket.setSoTimeout(130000); + + System.out.println(Arrays.toString(response)); + if(checkHandshake(response)) { + hasHandshake = true; + System.out.println("Connect:\n\t"+ this); + // no equals then stop thread for peer or wait + }else hasHandshake = false; + + } catch (Exception e) { + e.printStackTrace(); + hasHandshake = false; + + } + + return hasHandshake; + } + + // connect to host:port + public boolean connect() { + + boolean isConnected = false; + + try{ + this.socket = new Socket(this.host,this.port); + // channel in and out + this.in = this.socket.getInputStream(); + this.out = this.socket.getOutputStream(); + isConnected = true; + }catch (IOException e) { + e.printStackTrace(); + isConnected = false; + } + + + return isConnected; + } + + public byte[] genHandshake() { + return Peer.genHandshake(peer_id, infoHash); + } + /* + * + * Handshake: + * + * + */ + public static byte[] genHandshake(byte[] peer_id, byte[] infohash) { + int index = 0; + byte[] handshake = new byte[68]; + + // 0x13 19 DCN-MEAS DCN Measurement Subsystems Wikipedia: https://en.wikipedia.org/wiki/List_of_IP_protocol_numbers + handshake[index] = 0x13; + index++; + + // + System.arraycopy(Protocol, 0, handshake, index, Protocol.length); + index += Protocol.length; + + // 00000000 - no extension + System.arraycopy(new byte[8], 0, handshake, index, 8); + index += 8; + + // + System.arraycopy(infohash, 0, handshake, index, infohash.length); + index += infohash.length; + + // + System.arraycopy(peer_id, 0, handshake, index, peer_id.length); + + return handshake; + } + + public boolean checkHandshake(byte[] response) { + return checkHandshake(this.infoHash, response); + } + + public static boolean checkHandshake(byte[] infoHash, byte[] response) { + // for response + byte[] peerHash = new byte[20]; + System.arraycopy(response, 28, peerHash, 0, 20); + // == + if(!Arrays.equals(peerHash, infoHash)) + { + return false; + } + + return true; + } + + + + public ClientTorrent getTorrent_info() { + return client; + } + + public void setTorrent_info(ClientTorrent client) { + this.client = client; + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public byte[] getPeer_id() { + return peer_id; + } + + public void setPeer_id(byte[] peer_id) { + this.peer_id = peer_id; + } + + public Socket getSocket() { + return socket; + } + + public void setSocket(Socket socket) { + this.socket = socket; + } + + public InputStream getIn() { + return in; + } + + public void setIn(InputStream in) { + this.in = in; + } + + public OutputStream getOut() { + return out; + } + + public void setOut(OutputStream out) { + this.out = out; + } + public String toString() { + return ("host: "+this.host+"\t port: "+this.port+"\t connect: "+this.isConnected+"\t hasHandshake: "+ this.hasHandshake ); + } +} diff --git a/src/main/java/org/voyager/torrent/util/BinaryUtil.java b/src/main/java/org/voyager/torrent/util/BinaryUtil.java new file mode 100644 index 0000000..28c3c2c --- /dev/null +++ b/src/main/java/org/voyager/torrent/util/BinaryUtil.java @@ -0,0 +1,41 @@ +package org.voyager.torrent.util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.ByteBuffer; +import java.util.Map; +import java.util.Random; + +public class BinaryUtil { + + public static byte[] genBinaryArray(int sizeArray) { + Random rand = new Random(System.currentTimeMillis()); + byte[] vector = new byte[sizeArray]; + + for (int i = 0; i < sizeArray; ++i) { + vector[i] = (byte) ('A' + rand.nextInt(26)); + } + + return vector; + } + + public static StringBuffer inputStreamReaderToStringBuffer(InputStreamReader reader) throws IOException { + + BufferedReader in = new BufferedReader( reader ); + String inputLine; + StringBuffer content = new StringBuffer(); + while ((inputLine = in.readLine()) != null) { + content.append(inputLine); + } + in.close(); + + return content; + } + + public static ByteBuffer stringToByteBuffer(String text) { + return ByteBuffer.wrap( text.getBytes() ); + }; + + +} diff --git a/src/main/java/org/voyager/torrent/util/HttpUtil.java b/src/main/java/org/voyager/torrent/util/HttpUtil.java new file mode 100644 index 0000000..bdf012a --- /dev/null +++ b/src/main/java/org/voyager/torrent/util/HttpUtil.java @@ -0,0 +1,61 @@ +package org.voyager.torrent.util; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.Map; + +public class HttpUtil { + + /** The Constant HEX_CHARS. */ + public static final char[] HEX_CHARS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + + + + public static String getParamsString(Map params) + throws UnsupportedEncodingException{ + StringBuilder result = new StringBuilder(); + + for (Map.Entry entry : params.entrySet()) { + result.append(URLEncoder.encode(entry.getKey(), "UTF-8")); + result.append("="); + result.append(entry.getValue()); + //result.append(URLEncoder.encode(entry.getValue(), "UTF-8")); + result.append("&"); + } + + String resultString = result.toString(); + return resultString.length() > 0 + ? resultString.substring(0, resultString.length() - 1) + : resultString; + } + + /** + * To hex string. + * + * Converts a byte array to a hex string + * + * @param bytes the bytes + * @return the string + */ + public static String toHexString(byte[] bytes) { + if (bytes == null) { + return null; + } + + if (bytes.length == 0) { + return ""; + } + + StringBuilder sb = new StringBuilder(bytes.length * 3); + + for (byte b : bytes) { + byte hi = (byte) ((b >> 4) & 0x0f); + byte lo = (byte) (b & 0x0f); + + sb.append('%').append(HEX_CHARS[hi]).append(HEX_CHARS[lo]); + } + return sb.toString(); + } + +} diff --git a/src/main/java/org/voyager/torrent/util/ReaderBencode.java b/src/main/java/org/voyager/torrent/util/ReaderBencode.java new file mode 100644 index 0000000..bfe30f9 --- /dev/null +++ b/src/main/java/org/voyager/torrent/util/ReaderBencode.java @@ -0,0 +1,67 @@ +package org.voyager.torrent.util; + + +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.ByteBuffer; +import java.util.Map; + +import GivenTools.Bencoder2; +import GivenTools.BencodingException; +import GivenTools.TorrentInfo; + +import static java.lang.System.out; + +public class ReaderBencode { + + public static Map bencodeToMap(StringBuffer content) throws BencodingException{ + return bencodeToMap(content.toString().getBytes()); + } + public static Map bencodeToMap(String content) throws BencodingException{ + return bencodeToMap(content.getBytes()); + } + public static Map bencodeToMap(byte[] bencoded_bytes) throws BencodingException{ + return (Map)Bencoder2.decode(bencoded_bytes); + } + + /* read file .torrent*/ + public static TorrentInfo parseTorrentFile(File torrentFile) { + + try { + DataInputStream dataInputStream = new DataInputStream(new FileInputStream(torrentFile)); + long fSize = torrentFile.length(); + + if (fSize > Integer.MAX_VALUE || fSize < Integer.MIN_VALUE) { + dataInputStream.close(); + throw new IllegalArgumentException(fSize + " is too large a torrent filesize for this program to handle"); + } + + byte[] torrentData = new byte[(int)fSize]; + dataInputStream.readFully(torrentData); + TorrentInfo torrentInfo = new TorrentInfo(torrentData); + + dataInputStream.close(); + + out.println("Successfully parsed torrent file."); + + return torrentInfo; + } catch (FileNotFoundException e) { + out.println("Error: File not found"); + return null; + } catch (IOException e) { + out.println("errrrr"); + return null; + } catch (IllegalArgumentException e) { + out.println("Error: Illegal argument"); + return null; + } catch (BencodingException e) { + e.printStackTrace(); + out.println("Error: Invalid torrent file specified"); + return null; + } + } +} diff --git a/target/classes/org/voyager/torrent/Main.class b/target/classes/org/voyager/torrent/Main.class index e8827872f5a3a55decbdecd7669a1a7e1ed4f092..da562490694c567798914777ba9b6c256e46e80c 100644 GIT binary patch delta 380 zcmZ{g%Syvg5QhI#dx!Ri#VxkH#3Ks|NrL9JjNfA`sdHv2Y>@~=K9x6!x}@jXGx)4IZ-|32Z4}E zM+QX$C9E@~x#JA|sCwdhf}zmv-|{K9JT6DpKn1QG9d>RaN7+CHNruEk@qidL)Kl1G zsGYh~A&0*2O{^m!ZQmi!@x3j^73KQUKqGRQV?wEc;`ZGz;I^25U$q#`tM~u4NA9N! zc0SXwLOU5?6cd!wl$WszlPW2CPZ7fst*3O^>5cc1_lO02FZzBpC(UZjF>FKkc I;$S@z0BE@ltN;K2 diff --git a/target/classes/org/voyager/torrent/client/ClientTorrent.class b/target/classes/org/voyager/torrent/client/ClientTorrent.class index f3a260545feceabe5b9330a833ba43aad5fb2be4..0df6746d8862910b0de20322a4b495e030c0e191 100644 GIT binary patch literal 5447 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 delta 597 zcmY*VT~8B16g_t<-RU|lrC?h{P^m~ipo=Je6;UDa!3Po`G2wxSjV!R(cFlGn;mO}% z=G7m8lC(q;UrGD{{tA8r@y-;Z%p~{DoO{kacjm16TV#J-{P+prA(m`dgtA(7M!(cH z--(3}&7d8`i-bhE@}6*QIo$FE(uB-*(Ddsa|C1MaaTqxm#E^|FA-m@tcy7~c@3`xS zo!D_#~!mJh(c7X)aMlMP;q|bRJ_4@|c#GL0zp`jY=M~ zl3!jTh&Ws~^b`n>By1!F<_T2Sz*E(=W|IwV?Wl9Br8WmEpA$&wC-L8-#oZI!@1gn~BVE+GaE~#kNx8>Y!6)Ci zjfH0%GhlzPui!nyZqH2#?8!4;I=h^S@qua&FaBwheb7kc<#_=wnMhc~D~@{XY0g?~ X(UFeEwXaMYWuY&%@K^fU(BAw3om5~= diff --git a/workspace.torrent b/workspace.torrent new file mode 100644 index 0000000..aa5d8ce --- /dev/null +++ b/workspace.torrent @@ -0,0 +1,2 @@ +d8:announce30:udp://wambo.club:1337/announce13:announce-listll30:udp://wambo.club:1337/announceel45:udp://tracker.dutchtracking.com:6969/announceel38:udp://tc.animereactor.ru:8082/announceel35:udp://tracker.uw0.xyz:6969/announceel40:udp://tracker.kamigami.org:2710/announceel37:http://tracker.files.fm:6969/announceel41:udp://opentracker.i2p.rocks:6969/announceel41:udp://tracker.zerobytes.xyz:1337/announceel38:https://tracker.nitrix.me:443/announceel34:http://novaopcj.icu:10325/announceel28:udp://aaa.army:8866/announceel42:https://tracker.imgoingto.icu:443/announceel38:udp://tracker.shkinev.me:6969/announceel29:udp://blokas.io:6969/announceel42:udp://api.bitumconference.ru:6969/announceel32:udp://cutiegirl.ru:6969/announceel33:udp://ln.mtahost.co:6969/announceel34:udp://vibe.community:6969/announceel37:udp://tracker.vulnix.sh:6969/announceel37:udp://wassermann.online:6969/announceel30:udp://kanal-4.de:6969/announceel32:udp://mts.tvbit.co:6969/announceel39:udp://adminion.n-blade.ru:6969/announceel37:udp://benouworldtrip.fr:6969/announceel40:udp://sd-161673.dedibox.fr:6969/announceel38:udp://47.ip-51-68-199.eu:6969/announceel39:udp://cdn-1.gamecoast.org:6969/announceel32:udp://daveking.com:6969/announceel29:http://rt.tace.ru:80/announceel45:udp://forever-tracker.zooki.xyz:6969/announceel42:udp://free-tracker.zooki.xyz:6969/announceel45:udp://tracker.publictracker.xyz:6969/announceel44:udp://tracker.skynetcloud.site:6969/announceel39:udp://tracker.altrosky.nl:6969/announceel33:http://5rt.tace.ru:60889/announceel42:https://tracker.lilithraws.cf:443/announceel42:http://tracker.sakurato.xyz:23333/announceel33:udp://open.stealth.si:80/announceel37:udp://zephir.monocul.us:6969/announceel39:http://tracker2.itzmx.com:6961/announceel39:http://tracker3.itzmx.com:6961/announceel39:http://h4.trakx.nibba.trade:80/announceel31:udp://line-net.ru:6969/announceel36:udp://tracker.dyne.org:6969/announceel39:udp://mail.realliferpg.de:6969/announceel40:udp://storage.groupees.com:6969/announceel37:udp://torrent.tdjs.tech:6969/announceel39:udp://tracker.v6speed.org:6969/announceel39:udp://cdn-2.gamecoast.org:6969/announceel33:udp://bms-hosxp.com:6969/announceel44:udp://teamspeak.value-wolf.org:6969/announceel33:udp://koli.services:6969/announceel39:udp://inferno.demonoid.is:3391/announceel39:udp://ipv4.tracker.harry.lu:80/announceel38:udp://tracker.cyberia.is:6969/announceel33:udp://tracker.ds.is:6969/announceel41:udp://retracker.akado-ural.ru:80/announceel39:udp://discord.heihachi.pw:6969/announceel40:udp://chanchan.uchuu.co.uk:6969/announceel38:udp://aruacfilmes.com.br:6969/announceel31:udp://edu.uifr.ru:6969/announceel37:udp://publictracker.xyz:6969/announceel37:udp://www.torrent.eu.org:451/announceel36:http://vps02.net.orel.ru:80/announceel35:udp://bt2.archive.org:6969/announceel39:http://tracker.noobsubs.net:80/announceel34:udp://tracker.zum.bi:6969/announceel37:udp://dpiui.reedlan.com:6969/announceel30:udp://engplus.ru:6969/announceel31:udp://ultra.zt.ua:6969/announceel36:udp://nagios.tks.sumy.ua:80/announceel30:udp://61626c.net:6969/announceel31:udp://t2.leech.ie:1337/announceel40:https://trakx.herokuapp.com:443/announceel35:udp://bt1.archive.org:6969/announceel44:https://tracker.tamersunion.org:443/announceel31:udp://t1.leech.ie:1337/announceel48:udp://us-tracker.publictracker.xyz:6969/announceel40:udp://tracker.tiny-vps.com:6969/announceel36:udp://tracker.dler.org:6969/announceel36:http://t.nyaatracker.com:80/announceel31:udp://t3.leech.ie:1337/announceel32:udp://3rt.tace.ru:60889/announceel42:udp://retracker.lanta-net.ru:2710/announceel44:udp://valakas.rollo.dnsabr.com:2710/announceel47:udp://rutorrent.frontline-mod.com:6969/announceel41:udp://tracker.torrent.eu.org:451/announceel31:udp://opentor.org:2710/announceel36:udp://adm.category5.tv:6969/announceel32:udp://tracker.army:6969/announceel35:udp://tracker2.dler.org:80/announceel36:udp://tracker.fortu.io:6969/announceel29:http://bt.3kb.xyz:80/announceel32:udp://explodie.org:6969/announceel36:https://1337.abcvg.info:443/announceel39:udp://tracker0.ufibox.com:6969/announceel33:udp://movies.zsw.ca:6969/announceel35:udp://code2chicken.nl:6969/announceel28:udp://u.wwwww.wtf:1/announceel33:udp://tracker.0x.tf:6969/announceel37:http://publictracker.ch:6969/announceel36:udp://bioquantum.co.za:6969/announceel47:udp://www.midea123.z-media.com.cn:6969/announceel42:http://retracker.sevstar.net:2710/announceel49:udp://tracker.blacksparrowmedia.net:6969/announceel33:udp://git.vulnix.sh:6969/announceel43:udp://admin.videoenpoche.info:6969/announceee13:creation datei1651551106e8:encoding5:UTF-84:infod6:lengthi144e4:name12:.MyWorkspace12:piece lengthi65536e6:pieces20:†FK–ÕŸ’›-] +ß„‚“c­¨7:privatei0eee \ No newline at end of file