private void EndCheckEncryption(IAsyncResult result) { var id = (PeerId) result.AsyncState; try { byte[] initialData; EncryptorFactory.EndCheckEncryption(result, out initialData); if (initialData != null && initialData.Length == HandshakeMessage.HandshakeLength) { var message = new HandshakeMessage(); message.Decode(initialData, 0, initialData.Length); HandleHandshake(id, message); } else if (initialData == null || initialData.Length > 0) { throw new Exception("Argh. I can't handle this scenario. It also shouldn't happen. Ever."); } else { PeerIO.EnqueueReceiveHandshake(id.Connection, id.Decryptor, _handshakeReceivedCallback, id); } } catch { id.Connection.Dispose(); } }
private static void HandshakeReceived(bool successful, int transferred, object state) { var data = (ReceiveMessageState) state; PeerMessage message = null; if (successful) { data.Decryptor.Decrypt(data.Buffer, 0, transferred); message = new HandshakeMessage(); message.Decode(data.Buffer, 0, transferred); } data.Callback(successful, message, data.State); ClientEngine.BufferManager.FreeBuffer(data.Buffer); ReceiveCache.Enqueue(data); }
private static void HandshakeReceived(bool succeeded, int count, object state) { var result = (EncryptorAsyncResult) state; var connection = result.Id.Connection; try { if (!succeeded) throw new EncryptionException("Couldn't receive the handshake"); result.Available += count; var message = new HandshakeMessage(); message.Decode(result.Buffer, 0, result.Buffer.Length); var valid = message.ProtocolString == VersionInfo.ProtocolStringV100; var usable = CheckRc4(result.Id); var 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) { result.Complete(new EncryptionException("Invalid handshake received and no decryption works")); return; } // 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); } catch (Exception ex) { result.Complete(ex); } }
private void HandleHandshake(PeerId id, HandshakeMessage message) { TorrentManager man = null; try { if (message.ProtocolString != VersionInfo.ProtocolStringV100) throw new ProtocolException("Invalid protocol string in handshake"); } catch (Exception ex) { Debug.WriteLine(id.Connection, ex.Message); id.Connection.Dispose(); return; } man = Engine.Torrents.FirstOrDefault(t => message.InfoHash == t.InfoHash); ClientEngine.MainLoop.QueueWait(delegate { foreach (var t in Engine.Torrents.Where(t => message.InfoHash == t.InfoHash)) man = t; }); //FIXME: #warning FIXME: Don't stop the message loop until Dispose() and track all incoming connections if (man == null) // We're not hosting that torrent { //Debug.WriteLine("ListenManager - Handshake requested nonexistant torrent"); id.Connection.Dispose(); return; } if (man.State == TorrentState.Stopped) { Debug.WriteLine("ListenManager - Handshake requested for torrent which is not running"); id.Connection.Dispose(); return; } if (!man.Mode.CanAcceptConnections) { Debug.WriteLine("ListenManager - Current mode does not support connections"); id.Connection.Dispose(); return; } id.Peer.PeerId = message.PeerId; id.TorrentManager = man; // If the handshake was parsed properly without encryption, then it definitely was not encrypted. If this is not allowed, abort if ((id.Encryptor is PlainTextEncryption && !Toolbox.HasEncryption(Engine.Settings.AllowedEncryption, EncryptionTypes.PlainText)) && ClientEngine.SupportsEncryption) { Debug.WriteLine("ListenManager - Encryption is required but was not active"); id.Connection.Dispose(); return; } message.Handle(id); Debug.WriteLine("ListenManager - Handshake successful handled"); id.ClientApp = new Software(message.PeerId); message = new HandshakeMessage(id.TorrentManager.InfoHash, Engine.PeerId, VersionInfo.ProtocolStringV100); var callback = Engine.ConnectionManager.IncomingConnectionAcceptedCallback; PeerIO.EnqueueSendMessage(id.Connection, id.Encryptor, message, id.TorrentManager.UploadLimiter, id.Monitor, id.TorrentManager.Monitor, callback, id); }