public string Bencode() { Dictionary <string, object> dictionary = new Dictionary <string, object>(); this.serialize(dictionary, null); Bencoding.BElement bencoded = bencode(dictionary); string b = bencoded.ToBencodedString(); return(b); }
public string Bencode() { JavaScriptSerializer ser = new JavaScriptSerializer(); var json = ser.Serialize(this); // Deserialize into a dictionary and remove // empty attributes var jsonDict = ser.Deserialize <Dictionary <string, object> >(json); removeEmptyFields(ref jsonDict); Bencoding.BElement bencoded = bencode(jsonDict); string b = bencoded.ToBencodedString(); return(b); }
static int Main(string[] args) { #region Init string host = Dns.GetHostName(); IPHostEntry ip = Dns.GetHostEntry(host); for (int i = 0; i < ip.AddressList.Length; i++) { Console.WriteLine(ip.AddressList[i].ToString()); } Console.WriteLine(); string myip = ip.AddressList[0].ToString(); Encoding ibm437 = Encoding.GetEncoding(437); #endregion #region CommandLine // Check for command line argument then find designated file // Read from standard input if command line argument does not exist string path = ""; if (args.Length == 0) { Console.Write("No torrent file selected\n"); Console.Write("Input file name: "); path = Directory.GetCurrentDirectory() + @"\" + Console.ReadLine().Trim(); Console.WriteLine(path); Console.WriteLine(); } else { path = Directory.GetCurrentDirectory() + @"\" + args[0]; } #endregion #region ReadFile // Read file if (!File.Exists(path)) { Console.Write("Torrent file does not exist\n"); System.Threading.Thread.Sleep(FAIL_WAIT); return(1); } string payload = ""; Bencoding.BElement[] tfile = new Bencoding.BElement[0]; StreamReader read = new StreamReader(path, ibm437); payload = read.ReadToEnd(); tfile = Bencoding.BencodeDecoder.Decode(payload); #endregion #region TrackerStarter // Parse file // Get the primary tracker URL string trackerurl = ((Bencoding.BDictionary)(tfile[0]))["announce"].ToString(); // Build the HTTP GET request parameters string suffix = ""; suffix += @"?info_hash="; SHA1 infohash = new SHA1Managed(); string infostring = ((Bencoding.BDictionary)(tfile[0]))["info"].ToBencodedString(); infohash.ComputeHash(ibm437.GetBytes(infostring)); suffix += Byte2Hashstring(infohash.Hash); suffix += @"&peer_id="; string myid = "0F0F0F0F0F0F0F0F0F0F"; suffix += myid; suffix += @"&port="; suffix += IN_PORT; suffix += @"&uploaded="; long uploaded = 0; suffix += uploaded; suffix += @"&downloaded="; long downloaded = 0; suffix += downloaded; suffix += @"&left="; long left = Int64.Parse(((Bencoding.BDictionary)((Bencoding.BDictionary)(tfile[0]))["info"])["length"].ToBencodedString().Substring(1, ((Bencoding.BDictionary)((Bencoding.BDictionary)(tfile[0]))["info"])["length"].ToBencodedString().Length - 2)); suffix += left; suffix += @"&event=started"; suffix += @"&numwant="; suffix += NUM_WANT; suffix += @"&compact=1"; suffix += @"&no_peer_id=1"; // Change URL to HTTP prefix trackerurl = @"http://" + trackerurl.Substring(trackerurl.IndexOf(@"://") + 3); // Query the primary tracker string text = null; WebClient client = new WebClient(); try { Console.WriteLine(trackerurl); text = client.DownloadString(trackerurl + suffix); } catch (Exception e) { // If connection to tracker failed Console.WriteLine(e.GetBaseException().Message); client.Dispose(); } Bencoding.BElement[] response = new Bencoding.BElement[0]; bool failed = true; // Check if response is actually a failure if (text != null) { response = Bencoding.BencodeDecoder.Decode(text); if (response[0].ToBencodedString().IndexOf("failure reason") < 0) { failed = false; } } // If there was a failure try { // Try each alternate tracker for (int i = 0; failed && ((Bencoding.BList)((Bencoding.BDictionary)(tfile[0]))["announce-list"])[i] != null; i++) { string temp = ((Bencoding.BList)((Bencoding.BDictionary)(tfile[0]))["announce-list"])[i].ToBencodedString(); text = null; // Change prefix to HTTP if (temp.IndexOf("http://") < 0) { continue; } trackerurl = @"http://" + temp.Substring(temp.IndexOf("://") + 3, temp.Length - 1 - temp.IndexOf("://") - 3); client = new WebClient(); try { Console.WriteLine(); Console.WriteLine(trackerurl); text = client.DownloadString(trackerurl + suffix); } catch (Exception e) { // If connection to tracker failed Console.WriteLine(e.GetBaseException().Message); client.Dispose(); } response = new Bencoding.BElement[0]; failed = true; // Check if response is actually a failure if (text != null) { response = Bencoding.BencodeDecoder.Decode(text); if (response[0].ToBencodedString().IndexOf("failure reason") < 0) { failed = false; } } } } catch (Exception) { } // Check if all tracker connection attempts were failures Console.WriteLine(); if (!failed) { Console.WriteLine("Successfully connected to a tracker"); } else { Console.WriteLine("Could not connect to any trackers"); Thread.Sleep(FAIL_WAIT); return(1); } #endregion #region MainLoop // Parsing the tracker response long interval = ((Bencoding.BInteger)((Bencoding.BDictionary)(response[0]))["interval"]).Value; long timetoupdate = interval / 10 * 9; // Prime listener TcpListener inb = new TcpListener(IPAddress.Any, IN_PORT); inb.Server.Blocking = false; inb.Start(MAX_QUEUE); TcpClient[] peers = new TcpClient[0]; int[] peerttl = new int[0]; int[] am_choking = new int[0]; int[] am_interested = new int[0]; int[] peer_choking = new int[0]; long filelength = ((Bencoding.BInteger)((Bencoding.BDictionary)((Bencoding.BDictionary)(tfile[0]))["info"])["length"]).Value; long piecelength = ((Bencoding.BInteger)((Bencoding.BDictionary)((Bencoding.BDictionary)(tfile[0]))["info"])["piece length"]).Value; long numpieces = ((Bencoding.BString)((Bencoding.BDictionary)((Bencoding.BDictionary)(tfile[0]))["info"])["pieces"]).Value.Length / 20; string filename = ((Bencoding.BString)((Bencoding.BDictionary)((Bencoding.BDictionary)(tfile[0]))["info"])["name"]).Value; int[] peer_interested = new int[0]; bool[][] peer_pieces = new bool[0][]; bool[] have_pieces = new bool[numpieces + numpieces % 8]; // Main loop Console.Write("Starting Main Loop\n"); for (; ;) { #region TrackerQuery // Periodically request and parse HTTP information if (timetoupdate <= 0) { Console.WriteLine("-----------------------------------------------"); #region QueryTracker // Request tracker information suffix = ""; suffix += @"?info_hash="; suffix += Byte2Hashstring(infohash.Hash); suffix += @"&peer_id="; suffix += myid; suffix += @"&port="; suffix += IN_PORT; suffix += @"&uploaded="; suffix += uploaded; suffix += @"&downloaded="; suffix += downloaded; suffix += @"&left="; suffix += left; suffix += @"&numwant="; suffix += NUM_WANT; suffix += @"&compact=1"; suffix += @"&no_peer_id=1"; try { text = client.DownloadString(trackerurl + suffix); } catch (Exception e) { // If connection to tracker failed Console.WriteLine(e.GetBaseException().Message); client.Dispose(); } response = new Bencoding.BElement[0]; failed = true; // Check if response is actually a failure if (text != null) { response = Bencoding.BencodeDecoder.Decode(text); if (response[0].ToBencodedString().IndexOf("failure reason") < 0) { failed = false; } } if (failed) { Console.WriteLine("Connection with tracker broken"); Thread.Sleep(FAIL_WAIT); return(1); } #endregion interval = ((Bencoding.BInteger)((Bencoding.BDictionary)(response[0]))["interval"]).Value; timetoupdate = interval; #region ConnectToPeers // Parse tracker information string peerlist = ((Bencoding.BString)((Bencoding.BDictionary)(response[0]))["peers"]).ToBencodedString(); peerlist = peerlist.Substring(peerlist.IndexOf(":") + 1); int peerlen = peerlist.Length; for (int i = 0; i < peerlist.Length; i += 6) { // Convert response from byte data byte[] ipbytes = GetBytes(peerlist.Substring(i, 4)); byte[] portbytes = GetBytes(peerlist.Substring(i + 4, 2)); string ipstring = ipbytes[0] + "." + ipbytes[2] + "." + ipbytes[4] + "." + ipbytes[6]; int portint = portbytes[0] * (byte.MaxValue + 1) + portbytes[2]; // Sometimes I get weird data in between bytes // Actual IP and port number differ from what I calculate in these cases // I don't see a correlation between the noise and error so I drop them if (ipbytes[1] != 0 || ipbytes[3] != 0 || ipbytes[5] != 0 || ipbytes[7] != 0 || portbytes[1] != 0 || portbytes[3] != 0) { Console.WriteLine("\tSkip!"); continue; } Console.WriteLine("Outbound: {0}:{1}", ipstring, portint); // Attempt connection to peer try { TcpClient temppeer = new TcpClient(ipstring, portint); NetworkStream stream = temppeer.GetStream(); // Immediately send the handshake (Currently byte-wise representation of the data) byte[] handshake = new byte[MAX_HANDSHAKE]; // Pstrlen handshake[0] = (byte)PSTR.Length; // Pstr for (int i2 = 0; i2 < PSTR.ToCharArray().Length; i2++) { handshake[i2 + 1] = (byte)PSTR.ToCharArray()[i2]; } // Reserved // 8 bytes left as 0 for (int i2 = 0; i2 < infohash.Hash.Length; i2++) { handshake[1 + PSTR.Length + 8 + i2] = infohash.Hash[i2]; } // Peer ID for (int i2 = 0; i2 < myid.Length; i2++) { handshake[1 + PSTR.Length + 8 + infohash.Hash.Length + i2] = (byte)myid.ToCharArray()[i2]; } stream.Write(handshake, 0, 49 + PSTR.Length); //stream.Read(handshake, 0, handshake.Length); stream.Read(handshake, 0, 1); stream.Read(handshake, 1, 49 - 1 + handshake[0]); // Verify correct info_hash bool pass = true; for (int i2 = 0; i2 < infohash.Hash.Length; i2++) { if (infohash.Hash[i2] != handshake[1 + handshake[0] + 8 + i2]) { pass = false; break; } } if (!pass) { Console.WriteLine("\tDenied: Peer did not have matching info_hash"); temppeer.Close(); continue; } // Add peer to active peer list peers = TcpAdd(peers, temppeer); peerttl = IntAdd(peerttl, PEER_TTL); am_choking = IntAdd(am_choking, 1); am_interested = IntAdd(am_interested, 0); peer_choking = IntAdd(peer_choking, 1); peer_interested = IntAdd(peer_interested, 0); peer_pieces = BoolAdd(peer_pieces, new bool[numpieces + numpieces % 8]); Console.WriteLine("\tSuccess"); } catch (Exception e) { // Connection failed Console.Write("\tFailure: "); Console.WriteLine(e.GetBaseException().Message); } } #endregion } #endregion #region AcceptConnections // Accept incoming connections from peers while (inb.Pending()) { TcpClient temppeer; while ((temppeer = inb.AcceptTcpClient()) != null) { string ipstring = IPAddress.Parse(((IPEndPoint)temppeer.Client.RemoteEndPoint).Address.ToString()).ToString(); int portint = ((IPEndPoint)temppeer.Client.RemoteEndPoint).Port; Console.WriteLine("Inbound: {0}:{1}", ipstring, portint); // Immediately send the handshake (Currently byte-wise representation of the data) NetworkStream stream = temppeer.GetStream(); byte[] handshake = new byte[MAX_HANDSHAKE]; stream.Read(handshake, 0, handshake.Length); // Verify correct info_hash bool pass = true; for (int i2 = 0; i2 < infohash.Hash.Length; i2++) { if (infohash.Hash[i2] != handshake[1 + handshake[0] + 8 + i2]) { pass = false; break; } } if (!pass) { Console.WriteLine("\tDenied: Peer did not have matching info_hash"); temppeer.Close(); continue; } // Return handshake // Pstrlen handshake[0] = (byte)PSTR.Length; // Pstr for (int i2 = 0; i2 < PSTR.ToCharArray().Length; i2++) { handshake[i2 + 1] = (byte)PSTR.ToCharArray()[i2]; } // Reserved // 8 bytes left as 0 for (int i2 = 0; i2 < infohash.Hash.Length; i2++) { handshake[1 + PSTR.Length + 8 + i2] = infohash.Hash[i2]; } // Peer ID for (int i2 = 0; i2 < myid.Length; i2++) { handshake[1 + PSTR.Length + 8 + infohash.Hash.Length + i2] = (byte)myid.ToCharArray()[i2]; } stream.Write(handshake, 0, handshake.Length); peers = TcpAdd(peers, temppeer); peerttl = IntAdd(peerttl, PEER_TTL); am_choking = IntAdd(am_choking, 1); am_interested = IntAdd(am_interested, 0); peer_choking = IntAdd(peer_choking, 1); peer_interested = IntAdd(peer_interested, 0); peer_pieces = BoolAdd(peer_pieces, new bool[numpieces + numpieces % 8]); Console.WriteLine("Connection from peer accepted"); } } #endregion #region HandleConnections // Handle connections with peers for (int i = 0; i < peers.Length; i++) { string ipstring = IPAddress.Parse(((IPEndPoint)peers[i].Client.RemoteEndPoint).Address.ToString()).ToString(); int portint = ((IPEndPoint)peers[i].Client.RemoteEndPoint).Port; Console.WriteLine("Polling: {0}:{1}", ipstring, portint); if (peers[i].GetStream().DataAvailable) { peerttl[i] = PEER_TTL; NetworkStream stream = peers[i].GetStream(); byte[] buffer = new byte[MAX_BUFFER]; stream.Read(buffer, 0, 4); int len = buffer[0] * (byte.MaxValue + 1) * (byte.MaxValue + 1) * (byte.MaxValue + 1) + buffer[1] * (byte.MaxValue + 1) * (byte.MaxValue + 1) + buffer[2] * (byte.MaxValue + 1) + buffer[3] - 1; if (len == 0) { continue; } stream.Read(buffer, 4, 1); int id = buffer[4]; if (id == 0) { peer_choking[i] = 1; Console.WriteLine("Choking: {0}:{1}", ipstring, portint); continue; } if (id == 1) { peer_choking[i] = 0; Console.WriteLine("Unchoking: {0}:{1}", ipstring, portint); continue; } if (id == 2) { peer_interested[i] = 1; Console.WriteLine("Interested: {0}:{1}", ipstring, portint); continue; } if (id == 3) { peer_interested[i] = 0; Console.WriteLine("Uninterested: {0}:{1}", ipstring, portint); continue; } if (id == 4) { stream.Read(buffer, 0, 4); int length = buffer[0] * (byte.MaxValue + 1) * (byte.MaxValue + 1) * (byte.MaxValue + 1) + buffer[1] * (byte.MaxValue + 1) * (byte.MaxValue + 1) + buffer[2] * (byte.MaxValue + 1) + buffer[3]; Console.WriteLine("Have: {0}:{1} {2}", ipstring, portint, length); continue; } if (id == 5) { stream.Read(buffer, 0, len); peer_pieces[i] = new bool[numpieces + numpieces % 8]; for (int i2 = 0; i2 < len; i2++) { try { peer_pieces[i][i2 * 8 + 0] = (buffer[i2] >> 7) - (buffer[i2] >> 8 << 1) == 1; peer_pieces[i][i2 * 8 + 1] = (buffer[i2] >> 6) - (buffer[i2] >> 7 << 1) == 1; peer_pieces[i][i2 * 8 + 2] = (buffer[i2] >> 5) - (buffer[i2] >> 6 << 1) == 1; peer_pieces[i][i2 * 8 + 3] = (buffer[i2] >> 4) - (buffer[i2] >> 5 << 1) == 1; peer_pieces[i][i2 * 8 + 4] = (buffer[i2] >> 3) - (buffer[i2] >> 4 << 1) == 1; peer_pieces[i][i2 * 8 + 5] = (buffer[i2] >> 2) - (buffer[i2] >> 3 << 1) == 1; peer_pieces[i][i2 * 8 + 6] = (buffer[i2] >> 1) - (buffer[i2] >> 2 << 1) == 1; peer_pieces[i][i2 * 8 + 7] = (buffer[i2] >> 0) - (buffer[i2] >> 1 << 1) == 1; } catch (Exception) { break; } } Console.WriteLine("Bitfield: {0}:{1}", ipstring, portint); continue; } if (id == 6) { stream.Read(buffer, 0, 12); long index = buffer[0] * (byte.MaxValue + 1) * (byte.MaxValue + 1) * (byte.MaxValue + 1) + buffer[1] * (byte.MaxValue + 1) * (byte.MaxValue + 1) + buffer[2] * (byte.MaxValue + 1) + buffer[3]; long begin = buffer[4] * (byte.MaxValue + 1) * (byte.MaxValue + 1) * (byte.MaxValue + 1) + buffer[5] * (byte.MaxValue + 1) * (byte.MaxValue + 1) + buffer[6] * (byte.MaxValue + 1) + buffer[9]; long length = buffer[8] * (byte.MaxValue + 1) * (byte.MaxValue + 1) * (byte.MaxValue + 1) + buffer[9] * (byte.MaxValue + 1) * (byte.MaxValue + 1) + buffer[10] * (byte.MaxValue + 1) + buffer[11]; Console.WriteLine("Request: {0}:{1} {2},{3},{4}", ipstring, portint, index, begin, length); continue; } if (id == 7) { stream.Read(buffer, 0, 8); long index = buffer[0] * (byte.MaxValue + 1) * (byte.MaxValue + 1) * (byte.MaxValue + 1) + buffer[1] * (byte.MaxValue + 1) * (byte.MaxValue + 1) + buffer[2] * (byte.MaxValue + 1) + buffer[3]; long begin = buffer[4] * (byte.MaxValue + 1) * (byte.MaxValue + 1) * (byte.MaxValue + 1) + buffer[5] * (byte.MaxValue + 1) * (byte.MaxValue + 1) + buffer[6] * (byte.MaxValue + 1) + buffer[9]; long length = len - 8; stream.Read(buffer, 0, len - 8); // Create a file and write to it string tempname = filename + "." + index + "." + length; if (!File.Exists(tempname)) { File.Create(tempname); File.WriteAllBytes(tempname, buffer); } // Get all files for the same piece in directory List <string> filelist = new List <string>(); foreach (string s in Directory.GetFiles("", "*")) { filelist.Add(s); } int furthest = 0; int curpos = 0; Regex regex = new Regex("*." + index + ".[0-9]*.[0-9]*"); // Check if they can be combined to create full piece for (int i2 = 0; i2 < filelist.Count; i2++) { for (int i3 = 0; i3 < filelist.Count; i3++) { string cur = filelist.ElementAt(i3); if (!regex.IsMatch(cur)) { continue; } string cur2 = cur.Substring(cur.LastIndexOf('.')); string cur3 = cur.Substring(0, cur.Length - cur2.Length); string cur4 = cur3.Substring(cur3.LastIndexOf('.')); /* * if (Int64.Parse(cur2.Substring(1)) ) { * * } * */ } } Console.WriteLine("Piece: {0}:{1} {2},{3}", ipstring, portint, index, begin); continue; } if (id == 8) { stream.Read(buffer, 0, 12); long index = buffer[0] * (byte.MaxValue + 1) * (byte.MaxValue + 1) * (byte.MaxValue + 1) + buffer[1] * (byte.MaxValue + 1) * (byte.MaxValue + 1) + buffer[2] * (byte.MaxValue + 1) + buffer[3]; long begin = buffer[4] * (byte.MaxValue + 1) * (byte.MaxValue + 1) * (byte.MaxValue + 1) + buffer[5] * (byte.MaxValue + 1) * (byte.MaxValue + 1) + buffer[6] * (byte.MaxValue + 1) + buffer[9]; long length = buffer[8] * (byte.MaxValue + 1) * (byte.MaxValue + 1) * (byte.MaxValue + 1) + buffer[9] * (byte.MaxValue + 1) * (byte.MaxValue + 1) + buffer[10] * (byte.MaxValue + 1) + buffer[11]; Console.WriteLine("Cancel: {0}:{1} {2},{3},{4}", ipstring, portint, index, begin, length); continue; } } else if (peerttl[i] < 0) { peers[i].Close(); peers = TcpRemove(peers, i); peerttl = IntRemove(peerttl, i); am_choking = IntRemove(am_choking, i); am_interested = IntRemove(am_interested, i); peer_choking = IntRemove(peer_choking, i); peer_interested = IntRemove(peer_interested, i); i--; } } #endregion //for peers that are not choked // request pieces from outcoming traffic //check liveliness of peers and replace dead (or useless) peers //with new potentially useful peers //update peers #region Completion bool complete = true; for (int i = 0; i < numpieces; i++) { if (!have_pieces[i]) { complete = false; break; } } if (complete) { break; } #endregion #region WaitAndTimeUpdate Console.WriteLine(" - - - - - - - - - - - - - - - "); System.Threading.Thread.Sleep(MAIN_WAIT); timetoupdate -= MAIN_WAIT; for (int i = 0; i < peerttl.Length; i++) { peerttl[i] -= MAIN_WAIT; } #endregion } #endregion return(0); }