private static void HandshakeReceived(bool succeeded, int count, object state) { EncryptorAsyncResult result = (EncryptorAsyncResult)state; IConnection connection = result.Id.Connection; try { if (!succeeded) { throw new EncryptionException("Couldn't receive the handshake"); } result.Available += count; HandshakeMessage message = new HandshakeMessage(); message.Decode(result.Buffer, 0, result.Buffer.Length); bool valid = message.ProtocolString == VersionInfo.ProtocolStringV100; EncryptionTypes usable = CheckRC4(result.Id); bool canUseRC4 = Toolbox.HasEncryption(usable, EncryptionTypes.RC4Header) || Toolbox.HasEncryption(usable, EncryptionTypes.RC4Full); // If encryption is disabled and we received an invalid handshake - abort! if (valid) { result.InitialData = result.Buffer; result.Complete(); return; } if (!canUseRC4 && !valid) { result.Complete(new EncryptionException("Invalid handshake received and no decryption works")); return; } if (canUseRC4) { // The data we just received was part of an encrypted handshake and was *not* the BitTorrent handshake result.EncSocket = new PeerBEncryption(result.SKeys, EncryptionTypes.All); result.EncSocket.BeginHandshake(connection, result.Buffer, 0, result.Buffer.Length, CompletedEncryptedHandshakeCallback, result); } else { result.Complete(); } } catch (Exception ex) { result.Complete(ex); return; } }
private static void CompletedEncryptedHandshake(IAsyncResult result) { EncryptorAsyncResult r = (EncryptorAsyncResult)result.AsyncState; try { r.EncSocket.EndHandshake(result); r.Decryptor = r.EncSocket.Decryptor; r.Encryptor = r.EncSocket.Encryptor; r.InitialData = r.EncSocket.InitialData; } catch (Exception ex) { r.SavedException = ex; } r.Complete(); #if NETSTANDARD1_5 result.AsyncWaitHandle.Dispose(); r.AsyncWaitHandle.Dispose(); #else result.AsyncWaitHandle.Close(); r.AsyncWaitHandle.Close(); #endif }
internal static IAsyncResult BeginCheckEncryption(PeerId id, AsyncCallback callback, object state, byte[][] sKeys) { EncryptorAsyncResult result = new EncryptorAsyncResult(id, callback, state); result.SKeys = sKeys; IConnection c = id.Connection; try { // If the connection is incoming, receive the handshake before // trying to decide what encryption to use if (id.Connection.IsIncoming) { result.Buffer = new byte[id.BytesToRecieve]; NetworkIO.EnqueueReceive(c, result.Buffer, 0, result.Buffer.Length, HandshakeReceivedCallback, result); } else { EncryptionTypes usable = CheckRC4(id); bool hasPlainText = Toolbox.HasEncryption(usable, EncryptionTypes.PlainText); bool hasRC4 = Toolbox.HasEncryption(usable, EncryptionTypes.RC4Full) || Toolbox.HasEncryption(usable, EncryptionTypes.RC4Header); if (id.Engine.Settings.PreferEncryption) { if (hasRC4) { result.EncSocket = new PeerAEncryption(id.TorrentManager.Torrent.infoHash, usable); result.EncSocket.BeginHandshake(id.Connection, CompletedEncryptedHandshakeCallback, result); } else { result.Complete(); } } else { if (hasPlainText) { result.Complete(); } else { result.EncSocket = new PeerAEncryption(id.TorrentManager.Torrent.infoHash, usable); result.EncSocket.BeginHandshake(id.Connection, CompletedEncryptedHandshakeCallback, result); } } } } catch (Exception ex) { result.Complete(ex); } return result; }
internal static IAsyncResult BeginCheckEncryption(PeerId id, int bytesToReceive, AsyncCallback callback, object state, InfoHash[] sKeys) { var result = new EncryptorAsyncResult(id, callback, state) {SKeys = sKeys}; var c = id.Connection; ClientEngine.MainLoop.QueueTimeout(TimeSpan.FromSeconds(10), delegate { if (id.Encryptor == null || id.Decryptor == null) id.CloseConnection(); return false; }); try { // If the connection is incoming, receive the handshake before // trying to decide what encryption to use if (id.Connection.IsIncoming) { result.Buffer = new byte[bytesToReceive]; NetworkIO.EnqueueReceive(c, result.Buffer, 0, result.Buffer.Length, null, null, null, HandshakeReceivedCallback, result); } else { var usable = CheckRc4(id); var hasPlainText = Toolbox.HasEncryption(usable, EncryptionTypes.PlainText); var hasRc4 = Toolbox.HasEncryption(usable, EncryptionTypes.RC4Full) || Toolbox.HasEncryption(usable, EncryptionTypes.RC4Header); if (id.Engine.Settings.PreferEncryption) { if (hasRc4) { result.EncSocket = new PeerAEncryption(id.TorrentManager.InfoHash, usable); result.EncSocket.BeginHandshake(id.Connection, CompletedEncryptedHandshakeCallback, result); } result.Complete(); } else { if (hasPlainText) { result.Complete(); } else { result.EncSocket = new PeerAEncryption(id.TorrentManager.InfoHash, usable); result.EncSocket.BeginHandshake(id.Connection, CompletedEncryptedHandshakeCallback, result); } } } } catch (Exception ex) { result.Complete(ex); } return result; }
internal static IAsyncResult BeginCheckEncryption(PeerId id, int bytesToReceive, AsyncCallback callback, object state, InfoHash[] sKeys) { EncryptorAsyncResult result = new EncryptorAsyncResult(id, callback, state); result.SKeys = sKeys; IConnection c = id.Connection; ClientEngine.MainLoop.QueueTimeout(TimeSpan.FromSeconds(10), delegate { if (id.Encryptor == null || id.Decryptor == null) { id.CloseConnection(); } return(false); }); try { // If the connection is incoming, receive the handshake before // trying to decide what encryption to use if (id.Connection.IsIncoming) { result.Buffer = new byte[bytesToReceive]; NetworkIO.EnqueueReceive(c, result.Buffer, 0, result.Buffer.Length, null, null, null, HandshakeReceivedCallback, result); } else { EncryptionTypes usable = CheckRC4(id); bool hasPlainText = Toolbox.HasEncryption(usable, EncryptionTypes.PlainText); bool hasRC4 = Toolbox.HasEncryption(usable, EncryptionTypes.RC4Full) || Toolbox.HasEncryption(usable, EncryptionTypes.RC4Header); if (id.Engine.Settings.PreferEncryption) { if (hasRC4) { result.EncSocket = new PeerAEncryption(id.TorrentManager.InfoHash, usable); result.EncSocket.BeginHandshake(id.Connection, CompletedEncryptedHandshakeCallback, result); } else { result.Complete(); } } else { if (hasPlainText) { result.Complete(); } else { result.EncSocket = new PeerAEncryption(id.TorrentManager.InfoHash, usable); result.EncSocket.BeginHandshake(id.Connection, CompletedEncryptedHandshakeCallback, result); } } } } catch (Exception ex) { result.Complete(ex); } return(result); }