private async Task HandlePacket(BbTcpPacket packet) { if (packet is BbTcpPacket_Hello_Ans && m_bRequestedHello) { m_bRequestedHello = false; BbTcpPacket_Hello_Ans hello_ans = (BbTcpPacket_Hello_Ans)packet; ServerName = hello_ans.Desc; ServerGUID = hello_ans.ServerGUID; ServerMinProtocolVersion = hello_ans.MinSupportedVersion; m_bRequiresPassword = hello_ans.RequiresPassword; UsedProtocolVersion = (byte)Math.Min(hello_ans.MaxSupportedVersion, BBProtocol.CURRENT_PROTOCOL_VERSION); if (UsedProtocolVersion < hello_ans.MinSupportedVersion || UsedProtocolVersion < BBProtocol.MIN_PROTOCOL_VERSION) { ProtocolIncompatible = true; Log.w(TAG, "Server supported protocol versions incompatible - " + ServerName); Disconnect(false, true); } SupportsScreenCapture = hello_ans.SupportsScreenCapture; IsProVersion = hello_ans.IsProVersion; Log.d(TAG, "Received Hello Answer from " + ServerName + " Protocol Version: " + UsedProtocolVersion + " Needs Password: "******"Got Pong"); } else if (packet is BbTcpPacket_EncryptionACK crypt) { await ContinueEncryptionNegotiation(crypt); } else if (packet is BbTcpPacket_Encryption_AuthAns auth) { if (m_abyTestedSharedSecret != null) { if (auth.ErrorCode == 0) { Log.d(TAG, "DH+Auth negotiated encryption key for session is: " + BitConverter.ToString(m_abyTestedSharedSecret)); m_sendStreamCipher.Init(m_abyTestedSharedSecret); m_recvStreamCipher.Init(m_abyTestedSharedSecret); m_bAuthentificated = true; m_abyTestedSharedSecret = null; m_dhKeyExchange = null; m_requestedEncryptionMethod = EEncryptionMethod.NONE; Log.d(TAG, "Password accepted, DH+Auth Encryption negotiation finished, transmissions will now be encrypted with " + m_sendStreamCipher.Algorithm); Attach(); } else { Log.w(TAG, "Challenge failed - Password rejected. Trying again."); m_abyTestedSharedSecret = null; await Authenticate(true); } } else { Log.e(TAG, "Unexpected/Unrequested Encryption_AuthAns packet"); Disconnect(false, false); } } else if (packet is BbTcpPacket_Attach_Ans attach_ans && m_bRequestedAttach) { m_bRequestedAttach = false; if (attach_ans.AttachResult == EAttachResult.ACCEPTED) { Attached = true; WasAttached = true; ConnectedTime.Start(); Connecting = false; ConnectionChanged?.Invoke(this, new ConnectionEventArgs(ConnectionEventArgs.EState.CONNECTED, SessionID)); Log.d(TAG, "Attached to " + ServerName); } else { Log.d(TAG, "Cannot Attach to " + ServerName + " Error: " + attach_ans.AttachResult); Disconnect(false, false); } }
private async Task ReceiveTask() { NetworkStream stream; try { stream = m_tcpClient.GetStream(); } catch (InvalidOperationException e) { throw new IOException("Receive: Unable to get stream (not connected?) - " + e.Message, e); } List <BbTcpPacket_Fragment> liFragments = new List <BbTcpPacket_Fragment>(); while (true) { m_CancelToken.Token.ThrowIfCancellationRequested(); try { byte[] byHeader = new byte[BBProtocol.TCP_HEADERSIZE]; int read = 0; while (read != byHeader.Length) { int len = await stream.ReadAsync(byHeader, read, byHeader.Length - read, m_CancelToken.Token); if (len <= 0) { throw new IOException("Read < 0"); } read += len; m_CancelToken.Token.ThrowIfCancellationRequested(); } if (m_recvStreamCipher.IsReady) { m_recvStreamCipher.Crypt(byHeader); } BbTcpPacket newPacket = new BbTcpPacket(byHeader); if (newPacket.IsValid) { if (newPacket.IsComplete) { newPacket = newPacket.ReadPacket(new byte[0], UsedProtocolVersion); } else { byte[] byBody = new byte[newPacket.BodyLength]; read = 0; while (read != byBody.Length) { int len = await stream.ReadAsync(byBody, read, byBody.Length - read, m_CancelToken.Token); if (len <= 0) { throw new IOException("Read < 0"); } read += len; m_CancelToken.Token.ThrowIfCancellationRequested(); } if (m_recvStreamCipher.IsReady) { m_recvStreamCipher.Crypt(byBody); } newPacket = newPacket.ReadPacket(byBody, UsedProtocolVersion); } if (newPacket.IsValid && newPacket.IsComplete) { if (newPacket is BbTcpPacket_Fragment) { //Log.d(TAG, "Fragment received"); BbTcpPacket_Fragment found = liFragments.Find(x => x.FragmentID == ((BbTcpPacket_Fragment)newPacket).FragmentID); if (found == null) { liFragments.Add((BbTcpPacket_Fragment)newPacket); } else if (found.addFragment((BbTcpPacket_Fragment)newPacket)) // add. complete? { newPacket = found.assemblePacket(); liFragments.Remove(found); if (newPacket != null) { //Log.d(TAG, "Fragment completed from Opcode: " + newPacket.DbgGetOpcode()); m_receivedPackets.Post(newPacket); } else { Log.d(TAG, "Error while completing Fragment: " + found.ParseError); throw new IOException("Error while completing Fragment: " + found.ParseError); } } } else { //Log.d(TAG, "New Packet received"); m_receivedPackets.Post(newPacket); } } else { Log.e(TAG, "Invalid Packet (body) received:" + newPacket.ParseError); throw new IOException("Invalid Packet (body) received:" + newPacket.ParseError); } } else { Log.e(TAG, "Invalid Packet (header) received:" + newPacket.ParseError); throw new IOException("Invalid Packet (header) received:" + newPacket.ParseError); } } catch (Exception e) when(e is NotSupportedException || e is ObjectDisposedException) { Log.e(TAG, "Error while reading: " + e.Message + " stack: " + e.StackTrace); throw new IOException("Error while reading", e); } } }