Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A seeding client refuses to seed #627

Closed
ManlyMarco opened this issue Feb 3, 2023 · 17 comments
Closed

A seeding client refuses to seed #627

ManlyMarco opened this issue Feb 3, 2023 · 17 comments

Comments

@ManlyMarco
Copy link

ManlyMarco commented Feb 3, 2023

Looks like I've hit a new issue. The seeding client refuses to seed one of the auto generated torrents. There's no errors generating it nor adding it, and the tracker works fine. The peer connects to the seed, but the seed closes the connection immediately (tested both in a monotorrent client and uTorrent 2.2.1, in monotorrent the seed gets removed from the peers list immediately after it's added while uTorrent periodically tries to connect but the seed closes the connection immediately).

The torrent contains a very large amount of small files, it's 163KB with only V1 hashes. I'm guessing it's something about that. Other torrents generated in the same way seed fine.
There's nothing in the log outside of this:

Client log:

[18:56:37] INFO: ConnectionManager:ipv4://xx.xx.xxx.xxx:15847/: Connection opened
[18:56:37] INFO: ConnectionManager:ipv4://xx.xx.xxx.xxx:15847/: [outgoing] Sending handshake message with peer id '-MO3000-374654087375'

Server log:

INFO: ListenManager:ipv4://yyy.yyy.yy.yyy:51952/: ConnectionReceived

Packet dump: stuck.zip

@alanmcgovern
Copy link
Owner

Hrm, i can't get tell from the wireshark dump as the only two messasges visible in it are the two handshakes (one going each way).

The peer connects to the seed, but the seed closes the connection immediately (tested both in a monotorrent client and uTorrent 2.2.1, in monotorrent the seed gets removed from the peers list immediately after it's added while uTorrent periodically tries to connect but the seed closes the connection immediately

Is this a private torrent? If so it's possible the connection is being closed due to the peer id reported to the tracker being different to the peer id received by the client which established the outgoing connection.

i.e.
peer A connects to the tracker and receives a list of peers, including peer B and peer B's peer id.
peer A connects to peer B
peer A sends a handshake to peer B containing peer A's peer id
peer B accepts this and responds with it's handshake , containing peer B's peer id.
peer A closes the connection if peer B reported a different peer ID to the one it expected to receive.

This is something i'm going to address as part of #614 (comment) , though if this were actually happening in your case it should show in the seeder/leecher logs (whichever client initiates the connection should log that it's closing the connection due to the mismatch).

alanmcgovern added a commit that referenced this issue Feb 5, 2023
If a connection has already been made to a particular ip/port and
the peer_id is known, or if a non-compact response is returned by
the tracker so the peer_id for a given remote ip/port is 'known',
do *not* close the connection if the actual client at that ip/port
returns a different peer_id.

While the torrent spec requires that these connections be closed,
there are a few reasons which make this fairly pointless.

1) libtorrent randomises these by default. Other clients probably
randomise these too.

2) It's normal for these to change when a client restarts anyway.
Clients may be restarted for any number of reasons.

3) They're not transmitted by DHT, and are not transmitted by
the tracker by default.

4) The onus is on the *connecting* peer to close the connection,
which means the check is only 50% effective anyway. A client
could still join the swarm by making outgoing connections to
other peers.

If someone really wants this enabled, it can be enabled on a
per-torrent basis using the new setting in TorrentSettings.

Probably address #627
alanmcgovern added a commit that referenced this issue Feb 5, 2023
If a connection has already been made to a particular ip/port and
the peer_id is known, or if a non-compact response is returned by
the tracker so the peer_id for a given remote ip/port is 'known',
do *not* close the connection if the actual client at that ip/port
returns a different peer_id.

While the torrent spec requires that these connections be closed,
there are a few reasons which make this fairly pointless.

1) libtorrent randomises these by default. Other clients probably
randomise these too.

2) It's normal for these to change when a client restarts anyway.
Clients may be restarted for any number of reasons.

3) They're not transmitted by DHT, and are not transmitted by
the tracker by default.

4) The onus is on the *connecting* peer to close the connection,
which means the check is only 50% effective anyway. A client
could still join the swarm by making outgoing connections to
other peers.

If someone really wants this enabled, it can be enabled on a
per-torrent basis using the new setting in TorrentSettings.

Probably address #627
@ManlyMarco
Copy link
Author

ManlyMarco commented Feb 5, 2023

The torrent was set to public for using AddPeer to test if manually adding the seed helps anything, so being private doesn't matter. It seems to happen more often the more files there are in the torrent, but it's not consistent at all. It happens the most often on a torrent with around 1200 files, most around 450KB (I'm using V1 only mode). I added extra logging to the server to try to find any sort of clue as to what is happening, but it decided to work correctly after the server restart. I'll post an update if I learn anything new.

alanmcgovern added a commit that referenced this issue Feb 5, 2023
If a connection has already been made to a particular ip/port and
the peer_id is known, or if a non-compact response is returned by
the tracker so the peer_id for a given remote ip/port is 'known',
do *not* close the connection if the actual client at that ip/port
returns a different peer_id.

While the torrent spec requires that these connections be closed,
there are a few reasons which make this fairly pointless.

1) libtorrent randomises these by default. Other clients probably
randomise these too.

2) It's normal for these to change when a client restarts anyway.
Clients may be restarted for any number of reasons.

3) They're not transmitted by DHT, and are not transmitted by
the tracker by default.

4) The onus is on the *connecting* peer to close the connection,
which means the check is only 50% effective anyway. A client
could still join the swarm by making outgoing connections to
other peers.

If someone really wants this enabled, it can be enabled on a
per-torrent basis using the new setting in TorrentSettings.

Probably address #627
@ManlyMarco
Copy link
Author

ManlyMarco commented Feb 5, 2023

It looks like no exceptions are thrown when this happens.

It seems that after restarting the server side app, the seed always works fine, but it stops working after either restarting the client and starting the download over a few times, or after letting the seed idle for a while, not sure which one. It could also just be luck, but once it stops working it stops working for good, maybe it's something related to open connections?

If you have any test builds I could try to find the issue, let me know.

Edit: This issue is constrained to a particular torrent - with multiple torrents being seeded if I manage to get the bug to happen it only happens for a single torrent (unless I manage to trigger it again with another torrent). When the bug is active, it looks like no one can download the bugged torrent from the seed, even if it's their first time connecting (they can download other non-bugged torrents just fine).

Edit2: Could this be related to the max open file limit? I just noticed I had it set to 200 while the torrents easily surpassed that. I'll try bumping the value up and see what happens. When testing I was using only one client, downloading one torrent (but I had all torrents added to the client and started to seed them, so the seed shouldn't be affected by that).

@alanmcgovern
Copy link
Owner

@ManlyMarco By any chance is TorrentManager.State set to TorrentState.Error for the TorrentManager which bugged? If so, what's the value stored in TorrentManager.Error ?

@ManlyMarco
Copy link
Author

Good idea, I'll add logging to TorrentStateChanged on the server. The client is always in the Downloading state.

@ManlyMarco
Copy link
Author

ManlyMarco commented Feb 6, 2023

Alright, so the torrent keeps seeding, it doesn't error out.

Now that I've increased the open file limit to infinity, there is a change in behavior - the torrent in question still gets stuck, but now it actually does download, but at extremely low speed. The torrent has 1200+ of ~400KB files (1.7GB total, 1729 x 1.0MB pieces) and one of these downloads every minute or so, I think the delay is in between chunks being downloaded. At the same time there's a 950 file torrent (21GB total, 2707 x 8.0 MB pieces) being seeded by that very same instance, and it downloads just fine at connection speed limit.

Maybe the issue is related to having a ton of individual files that are smaller than the piece size? The client downloads only a subset of these files, around 200 or so, so maybe there's a performance issue? CPU and HDD usage of the process looks very low.

Edit: Preliminary testing with piece size set to 153600 looks very promising, no issues so far and speeds seem to be faster than ever for that particular torrent. Let's see if the issue comes back or not...

@alanmcgovern
Copy link
Owner

Now that I've increased the open file limit to infinity, there is a change in behavior - the torrent in question still gets stuck, but now it actually does download, but at extremely low speed. The torrent has 1200+ of ~400KB files (1.7GB total, 1729 x 1.0MB pieces) and one of these downloads every minute or so

Hrm, maybe I need to do some profiling with a 1,200 file torrent when 1000 of those are marked as 'DoNotDownload'? I can mock this scenario up pretty easily, so I'll do that and profile things to see if there's a measurable difference. The benchmarking I was trying locally was a 2,000 file torrent where each file was ~30kB, with piecesize of 1MB. I also set MaxOpenFiles to 3 to really stress things.

@ManlyMarco
Copy link
Author

ManlyMarco commented Feb 6, 2023

I'm not sure if setting files as DoNotDownload is important or not, trying to download everything at once with uTorrent after the issue happened resulted in a steady 10KBps download speed. If anything, it makes the issue more pronounced or easier to trigger.

Now that I reduced the piece size when generating this torrent the issue seems to be resolved since I can't make it happen despite doing the exact same steps that caused the bug before.

The file sizes vary from 1KB to 78MB, with most in the 200-400KB range. They are also placed in a bunch of different folders, though I doubt that affects anything.

@alanmcgovern
Copy link
Owner

monotorrent_as_seeder
monotorrent_as_seeder2
qbittorrent_as_seeder
qbittorrent_as_leecher

I created a torrent with 20,000 files, each 400kB in size using a loop like:

var buffer = new byte[400 * 1024];
var span = buffer.AsSpan ();
for (int i = 0; i < 20_000; i ++) {
    span.Fill ((byte) i);
    File.WriteAllBytes (buffer, $"{i}.data");
} 

Performance seems fine when:

  1. monotorrent seeds, monotorrent downloads.
  2. monotorrent seeds, qbittorrent downloads
  3. qbittorrent seeds, monotorrent downloads

If you do come up with a reasonably reliable way of triggering a performance issue, do let me know the steps and i'll try to reproduce the problem again. For now it seems ok as far as I can tell. I did try leaving the seeder alone for ages, then connecting. I also tried constantly disconnecting/reconnecting the leecher.

@ManlyMarco
Copy link
Author

ManlyMarco commented Feb 7, 2023

Yeah, unfortunately I have no idea what exactly triggers the issue, changing the piece size and increasing open file limit seems to have fixed it. Maybe it's specific to running on Linux and/or .NET 6.0 stand-alone? If I do figure out what exactly causes this I'll be sure to let you know.

@rjclarkewp007
Copy link

This sounds like the same issue I have. So I have a little game launcher which I coded (as a total noob!!) whereby players can download a game and then after they have downloaded the game, they also have the option to seed it for other downloaders.
So I am seeding my game from 4 servers using qBittorrent. Which works great, anyone that starts to download the game from my application will then download from these 4 peers, but when a player starts to share the game from my application then the application won't seed to new downloaders. Well sometimes it suddenly starts to seed to maybe one downloader, but there are sometimes maybe like 5 players downloading at the same time and still my application won't seed to any of them.

I can even do a test where i start seeding from my PC using my app and then start downloading from another PC on another network and then my seeding side just wont seed anything at all. The download side will only download from qBittorrent on those 4 servers. I still could not figure this out at all.. :(

@ManlyMarco
Copy link
Author

ManlyMarco commented Feb 10, 2023

@rjclarkewp007 Turn on debug logging (LoggerFactory.Register) and see what happens, if the connections are attempted but don't go through then maybe it's just because all clients have closed ports.

Back to my issue, it seems like it has been completely resolved. I don't see it happening any more, even under heavy client traffic.

@rjclarkewp007
Copy link

Thanks @ManlyMarco, i will give that a try as well. Just as a matter of interest, am I suppose to run something in a timed manner to update or search for more peers while busy downloading? Just asking because I mostly find that while downloading from my app and i start another download from lets say qBittorent, then my application will not download from that new downloader until the download in qBittorent is 100% complete. So it wont download chunks from an incomplete peer in other words.

@ManlyMarco
Copy link
Author

@rjclarkewp007 It should be able to download just fine before 100% without you doing anything special. Maybe the tracker update speed is slow and it takes a while for the client to query for new peers.

@rjclarkewp007
Copy link

rjclarkewp007 commented Feb 13, 2023

Thanks @ManlyMarco , Yeah i am still lost with this. Have no idea why my application will not seed to others. :( While bittorrent is seeding perfectly fine haha.

Here one can clearly see bitorrent seeding to 3 downloaders:
image

While my application is not seeding to them at all.. :(
image

I am still not even sure if it is the download part which is the problem or the seeding part which is the issue here. I tried to do that logging, but have not idea how that works so i can see a log of when/if any peers try to connect etc.

@rjclarkewp007
Copy link

oh and then all of a sudden it sees a leacher and starts to upload to only one hehe..
But i am seeding from 2 PC's with my application and only 1 computer sees this leacher. The other one not.. and both of them still not seeing the other two leachers.

image

@ManlyMarco
Copy link
Author

Everything works fine in my app now on the latest master builds, so I'll close this issue.

@rjclarkewp007 If it never connects then maybe ports it tries to use are closed on both sides. If you still have this issue I think you should open a new issue since this one got a bit off topic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants