Git Product home page Git Product logo

bitswarm's Introduction

BitSwarm: Bittorrent library (.net standard) for clients & streaming purposes

[Introduction]

BitSwarm implements Bittorrent Protocol v2 from scratch to achieve best performance and to expose low-level parameters for customization. It uses a custom thread pool and part files (APF) for fast resume from previous incomplete session.

[Supports]

  • Inputs (torrent file, magnet link, SHA1/Base32 hash)
  • Automatic Save & Load from a previous incomplete session
  • XML Import/Export Options for Timing/Feeding & Logging Configuration
  • Feeders (DHT, PEX, Trackers & External Trackers File)
  • Peers Communication (autonomous life-cycle with minimal dropped bytes)
  • Piece SHA1 validation & phony packets / broken clients protection
  • Start/End Game modes (fast metadata retrieval, initial boosting & closure)
  • Sleep mode for minimal resources usage (disables feeders & uses half threads based on specify download rate)
  • Focus Areas to bypass normal pieces selection (for streaming)
  • Dynamic change of options (eg) for streaming - useful for changing timeouts/retries during seeking/buffering for fast resets on requested pieces)

[Todo]

  • uTP
  • IPv6 DHT/Trackers
  • Download / Upload Rate Limits
  • Uploading / Seeding
  • VPN / Proxy / Encryption
  • NAT Traversal / PnP / Hole-punching

[Examples]

1. Library Overview

// Step 0: Prepare BitSwarm's Options (Timeouts/Feeders/Logging etc.)

Options opt = new Options();
	//opt.X = Y; check Options.cs for all available options

// Step 1: Create BitSwarm Instance

	// With Default Options
BitSwarm bitSwarm = new BitSwarm();
	// With Custom Options
BitSwarm bitSwarm = new BitSwarm(opt);

// Step 2: Subscribe events

	// Receives torrent data (on torrent file/session will fire directly, on magnetlink/hash will fire on metadata received - notify user with torrent detail and optionally choose which files to include)
bitSwarm.MetadataReceived   += BitSwarm_MetadataReceived; 	// e.Torrent
	// Receives statistics (refresh every 2 seconds - notify user with the current connections/bytes/speed of downloading)
bitSwarm.StatsUpdated       += BitSwarm_StatsUpdated;		// e.Stats
	// Notifies with the new status (notify user with 0: Finished, 1: Stopped, 2: Error)
bitSwarm.StatusChanged      += BitSwarm_StatusChanged;		// e.Status
	// Notifies that is going to stop (user can prevent it from finishing, by including other previously excluded files)
bitSwarm.OnFinishing        += BitSwarm_OnFinishing;		// e.Cancel

// Step 3: Open input (Current BitSwarm's valid inputs Torrent File/Magnet Link/SHA1 Hash/Base32 Hash/Session File)

	// Open Torrent File
bitSwarm.Open("/home/surgeonix/ubuntu.torrent");
	// Open Magnet Link
bitSwarm.Open("magnet:?xt=urn:btih:D1101A2B9D202811A05E8C57C557A20BF974DC8A");
	// Open SHA1 Hash
bitSwarm.Open("D1101A2B9D202811A05E8C57C557A20BF974DC8A");
	// Open Base32 (SHA1) Hash
bitSwarm.Open("RX46NCATYQRS3MCQNSEXVZGCCDNKTASQ");

// Step 4: Start downloading
bitSwarm.Start();

// Step 5: Dispose when you are done
bitSwarm.Dispose();

2. BitSwarm: Console Client (.NET Core)

3. BitSwarm: GUI Client (.NET Framework Winforms)

4. Flyleaf: Video Player & Torrent Streamer (.NET Framework Winforms)

Remarks

This project has been created for fun and educational reasons. Hopefully, it will help other developers to understand deeper the bittorrent protocol as the documentations and standards are very complicated and messy. I tried to add detailed comments within the code. Don't use it as is, it does not currently implement upload and sharing, which means that it is an arrogant and selfish beggar!

Logs Sample Stats Sample 1
Stats Sample 2 Stats Sample 3

bitswarm's People

Contributors

davepermen avatar surgeonix avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bitswarm's Issues

magnet link hangs

First: keep up the good work!
.open() does nothing with the following magnet link even in the WinForms demo.
magnet:?xt=urn:btih:ee17eb980ac506e3043474bf3fb42a7777ad991b&dn=Bitchin.Rides.S09E08.Is.There.Anything.Good.on.HDTV.x264-CRiMSON%5Brartv%5D&tr=http%3A%2F%2Ftracker.trackerfix.com%3A80%2Fannounce&tr=udp%3A%2F%2F9.rarbg.me%3A2760&tr=udp%3A%2F%2F9.rarbg.to%3A2780&tr=udp%3A%2F%2Ftracker.fatkhoala.org%3A13750&tr=udp%3A%2F%2Ftracker.thinelephant.org%3A12740

no error or other indication MetadataReceived never fires (or ANY of the events)

Firewall Rule - Inbound

Appears the application never initiates a firewall rule request to the Windows firewall allowing inbound connections, this can be helpful in allowing greater forwarding and connectivity.

For this, and the most forward approach I think is first add a new reference, browse COM and point path to
C:\WINDOWS\system32\FirewallAPI.dll

Now add the import

using NetFwTypeLib;

Next, add a new button to designer - button3

On click event

private void button3_Click(object sender, EventArgs e)
        {
            bool firewallRule = false;
            if (MessageBox.Show("Add a Allow All rule for Windows firewall?", "Confirmation", MessageBoxButtons.OKCancel) == DialogResult.OK)
            {
                // Located in FirewallAPI.dll
                INetFwRule firewallRule = (INetFwRule)Activator.CreateInstance(
                Type.GetTypeFromProgID("HNetCfg.FWRule"));
                firewallRule.Action = (NetFwTypeLib.NET_FW_ACTION_)NET_FW_ACTION_.NET_FW_ACTION_ALLOW;
                firewallRule.Description = "Used to allow all internet access.";
                firewallRule.Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN;
                firewallRule.Enabled = true;
                firewallRule.InterfaceTypes = "All";
                firewallRule.Name = "BitSwarm 2.4.4";
                INetFwPolicy2 firewallPolicy = (INetFwPolicy2)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwPolicy2"));
                firewallPolicy.Rules.Add(firewallRule);
                firewallRule = true;
            }
            if (firewallRule)
                MessageBox.Show("Firewall rule added successfully.");
        }

To remove rule, whether on program exit or by user control

firewallPolicy.Rules.Remove("BitSwarm 2.4.4");

Unlike most other applications listed by filename (Chrome uses their own name), this taps right into the Windows firewall API so you get the name, the values and directly in.

Its nice to have the firewall pop up window, but it seems this code bypasses that entirely.

This works 100%.

https://docs.microsoft.com/en-us/windows/win32/api/icftypes/

Question about multiple program transport stream

I have one multiple program transport stream (MPTS) with source IP address udp://@228.110.1.1:1234. I wanna develop a program like Mosaic Streaming player that detect available program in udp://@228.110.1.1:1234 till we choose one to play. (demux stream and extract programs baseid on PID or PMT ) this task done in VLC app but i cant switch between program and play one of theme، whiles DVB Viewer app play this stream in programs properly. my platform is .net and i am familiar with Flyleaf (your player) and libVLCSharp and ffplay and DVB viewer

`Core.Initialize();

_libVLC = new LibVLC();
_mediaPlayer = new MediaPlayer(_libVLC);

videoView.MediaPlayer = _mediaPlayer;

_mediaPlayer.Play(new Media(_libVLC, new Uri("... stream ip ...")));`

Do you have any idea for this task?

'System.IO.FileNotFoundException' in BencodeNET.dll

  •   Exception	Exception thrown: 'System.IO.FileNotFoundException' in BencodeNET.dll ("Could not load file or assembly 'System.Buffers, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The system cannot find the file specified.")	System.IO.FileNotFoundException
    

Torrent stream

Hi I would like to ask. It is possible to do a torrent stream as in monottorent example LVST. Thanks for the reply.

Multiple Process Instances - Threading Bug?

The client seems to make 3 application instances in memory when starting only 1 single torrent.

This can be confirmed by adding NotifyIcon1 to frmMain and watching for 3 spawn processes after starting a torrent. This is also a issue reflecting peer databases. On my end, a single query to the tracker for peers will add 3 rows into the database (for the same torrent, same instance. Really confuses the announce routines and gives up until next peer table clean interval).

This is a huge no no on nearly any tracker out there, especially older PHP4 trackers due to abuse/peer flooding/DDOS and the early days of the PHP team catching up.

If this is intended behavior, then the requests out to the tracker must be resolved.
Only 1 single unique info_hash should be sent out and acknowledged.

There are 3 rows with exact same data (and tells me its seeding, also no good). It seems to be retrying 3 times every time spawning a new instance? That is fine on the hardware-side of a consumer PC but for the database, this is a killer.

Please confirm.

CPU high usage for unix

It seems to be a .NET cores issue. To reproduce create few simple Threads and put them in a while (true) Sleep(10);

Other Purposes?

can i use your lib to use it for other purposes not for sending files. i want to build a p2p application based on bittorrent for sending/recieving data

Slow download speeds

Hi there

I have two questions.

  1. I can't seem to get more than 3000Kb/s download speed :( Is this normal?
  2. Is there a way to also seed the torrents while they are downloading?

I have integrated this into a small game launcher which will be downloading the game zip file and ideally i would like it to seed while downloading and also get the fastest download speeds possible.

When testing my torrent download using something like qbittorrent then i get full download speeds of 10Mb/s, but when I use my launcher with BitSwarm I get max 3Mb/s download speed.

Any ideas, please let me know.
thanks!

Private Torrents do not connect!

I have fully implemented this into a nice list control with internal BLOB fetch and save/load (and client begins downloads, like limewire sort of).

Works perfect on public torrents, but Private is not possible! uTorrent has absolutely no issues. I cant turn off Private flag in the metadata because that changes the info_hash (database mismatch, seedbox issues etc).

I will investigate but can you please provide a solution or confirmation?

I cant figure it out, I feel it is this line in Tracker.cs

byte[] sendBuff = System.Text.Encoding.UTF8.GetBytes($"GET {uri.AbsolutePath}?info_hash={Utils.StringHexToUrlEncode(options.InfoHash)}&peer_id={Utils.StringHexToUrlEncode(BitConverter.ToString(options.PeerId).Replace("-",""))}&port=11111&left={left}&downloaded={downloaded}&uploaded={uploaded}&event=started&compact=1&numwant={num_want} HTTP/1.1\r\nHost: {host}:{port}\r\nConection: close\r\n\r\n");

I plan to extend this codebase and push this thing forward. I already have it doing a lot, like notifications and much more, really cool library, thank you!

No Default User Agent Set

There is by default no user agent string set in the client's HTTP request headers. This can result in private-tracker penalties or other reductions in place of policy, libtorrent, trackers and possible utilization of these fields on the tracker-end. This could be otherwise treated as "Fake-Client" by mainland clients.

Changes:

Tracker.cs

static Tracker()
        {
            // Allowing Untrusted SSL Certificates with HttpClient
            ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
            httpClient.Timeout = new TimeSpan(0, 0, 30); // TODO: Options?
            var clientVersion = new ProductInfoHeaderValue("BitSwarm", "2.4.0");
            httpClient.DefaultRequestHeaders.UserAgent.Add(clientVersion);
        }

HttpClient Options

Added some options our other downloader classes uses, transfers work fine. May need tuning. C#9

Tracker.cs

using System.Security.Authentication;

static Tracker()
        {
            // Allowing Untrusted SSL Certificates with HttpClient
            var handler = new HttpClientHandler()
            {
                SslProtocols = SslProtocols.Tls12,
                AllowAutoRedirect = true,
                AutomaticDecompression = DecompressionMethods.GZip,
                CookieContainer = new CookieContainer()
            };
            using var httpClient = new HttpClient(handler);
            ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
            httpClient.Timeout = new TimeSpan(0, 0, 30); // TODO: Options?
            httpClient.DefaultRequestHeaders.UserAgent.Add(new System.Net.Http.Headers.ProductInfoHeaderValue("BitSwarm", BitSwarm.Version));
            key = rnd.Next(1, Int32.MaxValue);
        }
        public async void AnnounceTCP(Int32 num_want = -1, Int64 downloaded = 0, Int64 left = 0, Int64 uploaded = 0)
        {
            try
            {
                // Options?
                var handler = new HttpClientHandler()
                {
                    SslProtocols = SslProtocols.Tls12,
                    AllowAutoRedirect = true,
                    AutomaticDecompression = DecompressionMethods.GZip,
                    CookieContainer = new CookieContainer()
                };
                using var httpClient = new HttpClient(handler);
                string query = !string.IsNullOrEmpty(uri.Query) ? "&" : "?";
                query += $"info_hash={Utils.StringHexToUrlEncode(options.InfoHash)}&peer_id={Utils.StringHexToUrlEncode(BitConverter.ToString(options.PeerId).Replace("-", ""))}&port=11111&left={left}&downloaded={downloaded}&uploaded={uploaded}&event=started&compact=1&numwant={num_want}&key={key:x}";

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.