public void Teardown() { Incoming?.Dispose(); Outgoing?.Dispose(); }
static async ReusableTask <EncryptorResult> DoCheckIncomingConnectionAsync(IPeerConnection connection, IList <EncryptionType> preferredEncryption, InfoHash[] sKeys, Factories factories) { bool supportsRC4Header = preferredEncryption.Contains(EncryptionType.RC4Header); bool supportsRC4Full = preferredEncryption.Contains(EncryptionType.RC4Full); bool supportsPlainText = preferredEncryption.Contains(EncryptionType.PlainText); // If the connection is incoming, receive the handshake before // trying to decide what encryption to use using (NetworkIO.BufferPool.Rent(HandshakeMessage.HandshakeLength, out Memory <byte> buffer)) { await NetworkIO.ReceiveAsync(connection, buffer, null, null, null).ConfigureAwait(false); var message = new HandshakeMessage(buffer.Span); if (message.ProtocolString == Constants.ProtocolStringV100) { if (supportsPlainText) { return(new EncryptorResult(PlainTextEncryption.Instance, PlainTextEncryption.Instance, message)); } } else if (supportsRC4Header || supportsRC4Full) { // The data we just received was part of an encrypted handshake and was *not* the BitTorrent handshake // First switch to the threadpool as creating encrypted sockets runs expensive computations in the ctor await MainLoop.SwitchToThreadpool(); using var encSocket = new PeerBEncryption(factories, sKeys, preferredEncryption); await encSocket.HandshakeAsync(connection, buffer).ConfigureAwait(false); if (encSocket.Decryptor is RC4Header && !supportsRC4Header) { throw new EncryptionException("Decryptor was RC4Header but that is not allowed"); } if (encSocket.Decryptor is RC4 && !supportsRC4Full) { throw new EncryptionException("Decryptor was RC4Full but that is not allowed"); } // As the connection was encrypted, the data we got from the initial Receive call will have // been consumed during the crypto handshake process. Now that the encrypted handshake has // been established, we should ensure we read the data again. Memory <byte> data = encSocket.InitialData?.Length > 0 ? encSocket.InitialData : default; if (data.IsEmpty) { await NetworkIO.ReceiveAsync(connection, buffer, null, null, null).ConfigureAwait(false); encSocket.Decryptor !.Decrypt(buffer.Span); data = buffer; } message.Decode(data.Span); if (message.ProtocolString == Constants.ProtocolStringV100) { return(new EncryptorResult(encSocket.Decryptor !, encSocket.Encryptor !, message)); } } } connection.Dispose(); throw new EncryptionException("Invalid handshake received and no decryption works"); }