protected override async ValueTask PostHandling(P18PublicKeys packet, Message message)
        {
            // Get all direct channels of Alice
            var channels = await Database.ChannelMembers.AsQueryable()
                           .Where(m => m.AccountId == Client.AccountId)
                           .Join(Database.Channels, m => m.ChannelId, c => c.ChannelId, (m, c) => c)
                           .Where(c => c.ChannelType == ChannelType.Direct)
                           .ToListAsync().ConfigureAwait(false);

            foreach (Channel channel in channels)
            {
                long bobId = await Database.ChannelMembers.AsQueryable()
                             .Where(m => m.ChannelId == channel.ChannelId && m.AccountId != Client.AccountId)
                             .Select(m => m.AccountId).SingleAsync().ConfigureAwait(false);

                // Get Bob's latest public key packet in this channel and take Alice's new public key

                long bobPublicId = await Database.GetLatestPublicKey(bobId).ConfigureAwait(false);

                if (bobPublicId == default)
                {
                    continue;                         // The server will create the DirectChannelUpdate when Bob sends his public key
                }
                var directChannelUpdate = await injector
                                          .CreateDirectChannelUpdate(channel.ChannelId, Client.AccountId, message.MessageId, bobId, bobPublicId).ConfigureAwait(false);

                await Delivery.StartSendMessage(directChannelUpdate, null).ConfigureAwait(false);
            }
        }
        private async ValueTask CreateDirectChannel(long tempChannelId, long counterpartId)
        {
            var counterpart = await Database.Accounts.AsQueryable()
                              .SingleOrDefaultAsync(acc => acc.AccountId == counterpartId).ConfigureAwait(false);

            if (counterpart == null)
            {
                await Fail(CreateChannelStatus.InvalidCounterpart, tempChannelId).ConfigureAwait(false);

                return;
            }

            if (await Database.BlockedAccounts.AsQueryable()
                .AnyAsync(b => b.OwnerId == counterpartId && b.AccountId == Client.AccountId ||
                          b.OwnerId == Client.AccountId && b.AccountId == counterpartId)
                .ConfigureAwait(false))
            {
                await Fail(CreateChannelStatus.Blocked, tempChannelId).ConfigureAwait(false);

                return;
            }

            if (await Database.Channels.AsQueryable()
                .Where(c => c.ChannelType == ChannelType.Direct &&
                       ((c.OwnerId == Client.AccountId && c.CounterpartId == counterpartId) ||
                        (c.OwnerId == counterpartId && c.CounterpartId == Client.AccountId)))
                .AnyAsync().ConfigureAwait(false))
            {
                await Fail(CreateChannelStatus.AlreadyExists, tempChannelId).ConfigureAwait(false);

                return;
            }
            long aliceChannelId = await Database.Channels.AsQueryable()
                                  .Where(c => c.ChannelType == ChannelType.AccountData && c.OwnerId == Client.AccountId)
                                  .Select(c => c.ChannelId)
                                  .SingleAsync().ConfigureAwait(false);

            long bobChannelId = await Database.Channels.AsQueryable()
                                .Where(c => c.ChannelType == ChannelType.AccountData && c.OwnerId == counterpartId)
                                .Select(c => c.ChannelId)
                                .SingleAsync().ConfigureAwait(false);

            var tcs = new TaskCompletionSource <Channel>();

            // Register send operations before actually creating the channel to ensure
            // that all clients receive their P0ACreateChannel packet before any other messages
            Task responseTask = Client.Send(new CreateChannelEnumerable(Packets, tcs.Task, counterpartId, bobChannelId, tempChannelId));
            await Delivery.StartSendToAccount(new CreateChannelEnumerable(Packets, tcs.Task, counterpartId, bobChannelId), Client.AccountId, Client).ConfigureAwait(false);

            await Delivery.StartSendToAccount(new CreateChannelEnumerable(Packets, tcs.Task, Client.AccountId, aliceChannelId), counterpartId, null).ConfigureAwait(false);

            // Create a new direct channel
            Channel channel = await Database.AddChannel(
                new Channel
            {
                OwnerId       = Client.AccountId,
                ChannelType   = ChannelType.Direct,
                CounterpartId = counterpartId
            },
                new ChannelMember { AccountId = Client.AccountId },
                new ChannelMember { AccountId = counterpartId })
                              .ConfigureAwait(false);

            // Check for existing direct channels and delete if another channel was created in the meantime
            Channel first = await Database.Channels.AsQueryable()
                            .Where(c => c.ChannelType == ChannelType.Direct &&
                                   ((c.OwnerId == Client.AccountId && c.CounterpartId == counterpartId) ||
                                    (c.OwnerId == counterpartId && c.CounterpartId == Client.AccountId)))
                            .OrderBy(c => c.CreationTime)
                            .FirstAsync().ConfigureAwait(false);

            if (first.ChannelId != channel.ChannelId)
            {
                Database.Channels.Remove(channel);
                await Database.SaveChangesAsync().ConfigureAwait(false);

                tcs.SetResult(null);
            }
            else // This channel won the race and we continue processing
            {
                // Add channel memberships while send the send queue is locked
                Database.ChannelMembers.Add(new ChannelMember {
                    ChannelId = aliceChannelId, AccountId = counterpartId
                });
                Database.ChannelMembers.Add(new ChannelMember {
                    ChannelId = bobChannelId, AccountId = Client.AccountId
                });
                await Database.SaveChangesAsync().ConfigureAwait(false);

                tcs.SetResult(channel);

                // Start messages forwarding before injecting the direct channel update
                // Otherwise clients could not resolve the dependencies to the keys
                await Delivery.StartSyncMessages(Client.AccountId, bobChannelId).ConfigureAwait(false);

                await Delivery.StartSyncMessages(counterpartId, aliceChannelId).ConfigureAwait(false);

                long alicePublicId = await Database.GetLatestPublicKey(Client.AccountId).ConfigureAwait(false);

                long bobPublicId = await Database.GetLatestPublicKey(counterpart.AccountId).ConfigureAwait(false);

                if (alicePublicId != default && bobPublicId != default)
                {
                    var message = await injector
                                  .CreateDirectChannelUpdate(channel.ChannelId, Client.AccountId, alicePublicId, counterpart.AccountId, bobPublicId)
                                  .ConfigureAwait(false);

                    await Delivery.StartSendMessage(message, null).ConfigureAwait(false);
                }
            }

            await responseTask.ConfigureAwait(false);
        }