Skip to content

Commit

Permalink
Merge pull request #697 from alanmcgovern/better-peerid-creation
Browse files Browse the repository at this point in the history
Better handling of incoming and outgoing connections
  • Loading branch information
alanmcgovern authored Sep 9, 2024
2 parents 84b5911 + 49e513d commit e41e931
Show file tree
Hide file tree
Showing 18 changed files with 346 additions and 162 deletions.
53 changes: 5 additions & 48 deletions src/MonoTorrent.Client/MonoTorrent.Client.Modes/Mode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ namespace MonoTorrent.Client.Modes
abstract class Mode : IMode
{
static readonly Logger logger = Logger.Create (nameof (Mode));
static readonly SHA1 AllowedFastHasher = SHA1.Create ();

bool hashingPendingFiles;
ValueStopwatch lastSendHaveMessage;
Expand Down Expand Up @@ -217,57 +216,18 @@ protected virtual void HandleHashRejectMessage (PeerId id, HashRejectMessage has

public virtual bool ShouldConnect (Peer peer)
{
return peer.LastConnectionAttempt.Elapsed >= Settings.GetConnectionRetryDelay (peer.FailedConnectionAttempts);
return peer.WaitUntilNextConnectionAttempt.Elapsed >= Settings.GetConnectionRetryDelay (peer.FailedConnectionAttempts)
&& peer.WaitUntilNextConnectionAttempt.Elapsed >= Settings.GetConnectionRetryDelay (peer.CleanedUpCount);
}

protected virtual void HandleGenericExtensionMessage (PeerId id, ExtensionMessage extensionMessage)
{
// Do nothing
}

protected virtual void HandleHandshakeMessage (PeerId id, HandshakeMessage message)
void HandleHandshakeMessage (PeerId id, HandshakeMessage message)
{
if (!message.ProtocolString.Equals (Constants.ProtocolStringV100)) {
logger.InfoFormatted (id.Connection, "Invalid protocol in handshake: {0}", message.ProtocolString);
throw new ProtocolException ("Invalid protocol string");
}

// If we got the peer as a "compact" peer, then the peerid will be empty. In this case
// we just copy the one that is in the handshake.
if (BEncodedString.IsNullOrEmpty (id.Peer.Info.PeerId))
id.Peer.UpdatePeerId (message.PeerId);

// If the infohash doesn't match, dump the connection
if (!Manager.InfoHashes.Contains (message.InfoHash)) {
logger.Info (id.Connection, "HandShake.Handle - Invalid infohash");
throw new TorrentException ("Invalid infohash. Not tracking this torrent");
}

// If the peer id's don't match, dump the connection. This is due to peers faking usually
if (!id.Peer.Info.PeerId.Equals (message.PeerId)) {
if (Manager.Settings.RequirePeerIdToMatch) {
// Several prominent clients randomise peer ids (at the least, everything based on libtorrent)
// so closing connections when the peer id does not match risks blocking compatibility with many
// clients. Additionally, MonoTorrent has long been configured to default to compact tracker responses
// so the odds of having the peer ID are slim.
logger.InfoFormatted (id.Connection, "HandShake.Handle - Invalid peerid. Expected '{0}' but received '{1}'", id.Peer.Info.PeerId, message.PeerId);
throw new TorrentException ("Supplied PeerID didn't match the one the tracker gave us");
} else {
// We don't care about the mismatch for public torrents. uTorrent randomizes its PeerId, as do other clients.
id.Peer.UpdatePeerId (message.PeerId);
}
}

// Attempt to parse the application that the peer is using
id.ClientApp = new Software (message.PeerId);
id.SupportsFastPeer = message.SupportsFastPeer;
id.SupportsLTMessages = message.SupportsExtendedMessaging;

// If they support fast peers, create their list of allowed pieces that they can request off me
if (id.SupportsFastPeer && id.AddressBytes.Length > 0 && Manager != null && Manager.HasMetadata) {
lock (AllowedFastHasher)
id.AmAllowedFastPieces = AllowedFastAlgorithm.Calculate (AllowedFastHasher, id.AddressBytes.Span, Manager.InfoHashes, (uint) Manager.Torrent!.PieceCount);
}
throw new NotSupportedException ("The handshake message should be the first message received.");
}

protected virtual async void HandlePeerExchangeMessage (PeerId id, PeerExchangeMessage message)
Expand Down Expand Up @@ -750,11 +710,8 @@ void DownloadLogic (int counter)
if (connection == null)
continue;

var id = new PeerId (peer, connection, new BitField (Manager.Bitfield.Length).SetAll (true), Manager.InfoHashes.V1OrV2);
id.Encryptor = PlainTextEncryption.Instance;
id.Decryptor = PlainTextEncryption.Instance;
var id = new PeerId (peer, connection, new BitField (Manager.Bitfield.Length).SetAll (true), Manager.InfoHashes.V1OrV2, PlainTextEncryption.Instance, PlainTextEncryption.Instance, new Software (peer.Info.PeerId));
id.IsChoking = false;
id.ClientApp = new Software (id.PeerID);
Manager.Peers.ConnectedPeers.Add (id);
Interlocked.Increment (ref ConnectionManager.openConnections);
Manager.RaisePeerConnected (id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ public enum ConnectionFailureReason
/// </summary>
UnknownUriSchema,

/// <summary>
/// This peer has been banned. This can happen if the peer repeatedly sends data which fails a hashcheck, or it can happen if
/// the user of the library has used the <see cref="ConnectionManager.BanPeer"/> event to indicate the peer should be banned.
/// </summary>
ConnectedToSelf,

/// <summary>
/// After accepting the connection, a compatible connection encryption method could not
/// be selected. Alternatively the remote peer could have reached it's open connection
Expand Down
Loading

0 comments on commit e41e931

Please sign in to comment.