Exemple #1
0
        public void SendMessageToAllUsers(BroadcastMessageDto message)
        {
            Guard.IsNotNull(message);
            Guard.IsNotEmpty(message.Subject);
            Guard.IsNotEmpty(message.Body);

            // users cant be changed at this level! They will be fetched again in foreach and changed there
            var readOnlyUsers = _userService.GetAll(null, nameof(User.MessageConfig), null, null, true);

            foreach (var user in readOnlyUsers)
            {
                var messageForUser = CreateMessageDto(user.MessageConfig, message.Subject, message.Body);
                _userService.AddMessage(user.Id, messageForUser);
            }
        }
        public async Task BroadCastMessage_Calls_MessageService_Returns_Ok()
        {
            _seeder.ResetUsers();
            _seeder.AssignMessageConfigToAllUsers();
            var users = _seeder.GetAll <User>(nameof(User.MessageConfig));
            // ACT
            var broadCastMessageToSend = new BroadcastMessageDto("TestSubject", "TestBody");
            var response = await Client.PostAsync($"{PATH}/broadcastMessage",
                                                  _api.BuildJsonHttpContent(broadCastMessageToSend));

            var stringResponse = await response.Content.ReadAsStringAsync();

            _output.WriteLine(stringResponse);
            response.EnsureSuccessStatusCode();

            // ASSERT
            Assert.NotEmpty(stringResponse);
            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
        }
Exemple #3
0
 public IActionResult SendBroadcastMessage(BroadcastMessageDto message)
 {
     _messageService.SendMessageToAllUsers(message);
     return(Ok(message));
 }
Exemple #4
0
        private async Task SynchronizeRemoteToLocalAsync()
        {
            DebugPrint("Enter Remote to Local");
            var have = await ChannelsExtensions.ReadAsync(haveChannel).ConfigureAwait(false);

            DebugPrint("Have is {0}", have.MerkleRootHash);
            var isRemoteRootSyncedLocally = await IsRemoteObjectHeldLocally(have.MerkleRootHash).ConfigureAwait(false);

            DebugPrint("IRRSL {0}", isRemoteRootSyncedLocally);

            if (!isRemoteRootSyncedLocally)
            {
                var nodesToImport = new List <Tuple <string, MerkleNode> >();
                var neededHashes  = new LinkedList <string>();
                neededHashes.AddLast(have.MerkleRootHash);

                while (neededHashes.Count != 0)
                {
                    var hashesReadLocally = new HashSet <string>();
                    foreach (var hash in neededHashes)
                    {
                        var localNode = await localMerkleTree.GetNodeAsync(hash).ConfigureAwait(false);

                        if (localNode != null)
                        {
                            nodesToImport.Add(Tuple.Create(hash, localNode));
                            hashesReadLocally.Add(hash);
                            continue;
                        }

                        var need = new NeedPacket {
                            MerkleRootHash = hash
                        };
                        DebugPrint("SEND NEED {0}", need.MerkleRootHash);
                        neighbor.SendAsync(serializer.ToByteArray(need)).Forget();
                    }

                    Console.WriteLine($"Found {neededHashes.Count} messages to sync");
                    foreach (var i in Enumerable.Range(0, neededHashes.Count))
                    {
                        var hash = neededHashes.First();
                        neededHashes.RemoveFirst();

                        if (hashesReadLocally.Contains(hash))
                        {
                            continue;
                        }

                        var give = await ChannelsExtensions.ReadAsync(giveChannel).ConfigureAwait(false);

                        Console.WriteLine($"Got hash {give.NodeHash}");
                        nodesToImport.Add(Tuple.Create(give.NodeHash, give.Node));

                        if (!await IsRemoteObjectHeldLocally(give.Node.LeftHash).ConfigureAwait(false))
                        {
                            neededHashes.AddLast(give.Node.LeftHash);
                        }

                        if (!await IsRemoteObjectHeldLocally(give.Node.RightHash).ConfigureAwait(false))
                        {
                            neededHashes.AddLast(give.Node.RightHash);
                        }
                    }
                }

                var broadcastMessagesByNodeHash = nodesToImport.Where(n => n.Item2.TypeTag == MerkleNodeTypeTag.Data)
                                                  .ToDictionary(
                    n => n.Item1,
                    n => broadcastMessageSerializer.Deserialize(n.Item2.Contents)
                    );
                Console.WriteLine($"Need to add {broadcastMessagesByNodeHash.Count} hashes that we don't have");

                var neededSourceIdHashes = broadcastMessagesByNodeHash.Select(kvp => kvp.Value.SourceIdHash)
                                           .GroupBy(sourceIdHash => sourceIdHash.ToHexString())
                                           .Select(g => new { Bytes = g.First(), Hex = g.Key })
                                           .Where(pair => !IdentityManager.IsKnownIdentity(pair.Bytes))
                                           .ToList();

                foreach (var neededSourceId in neededSourceIdHashes)
                {
                    var whois = new WhoisPacket {
                        IdHash = neededSourceId.Bytes
                    };
                    DebugPrint("SEND WHOIS {0}", neededSourceId.Hex);
                    neighbor.SendAsync(serializer.ToByteArray(whois)).Forget();
                }

                foreach (var i in Enumerable.Range(0, neededSourceIdHashes.Count))
                {
                    var ident = await ChannelsExtensions.ReadAsync(identChannel).ConfigureAwait(false);

                    Identity.ValidateAndAdd(ident.TrustChain);
                }

                foreach (var neededSourceId in neededSourceIdHashes)
                {
                    if (!IdentityManager.IsKnownIdentity(neededSourceId.Bytes))
                    {
                        throw new InvalidStateException();
                    }
                }

                foreach (var tuple in nodesToImport)
                {
                    var node = tuple.Item2;
                    if (node.Descendents == 0 && await localMerkleTree.GetNodeAsync(tuple.Item1).ConfigureAwait(false) == null)
                    {
                        var isDataNode = node.TypeTag == MerkleNodeTypeTag.Data;
                        BroadcastMessageDto message = isDataNode ? broadcastMessageSerializer.Deserialize(node.Contents) : null;

                        var sender = IdentityManager.LookupIdentity(message.SourceIdHash);
                        if (message.DestinationIdHash.All(val => val == 0))
                        {
                            if ((sender.HeldPermissions & Permission.Broadcast) == 0)
                            {
                                Console.WriteLine("Sender does not have broadcast permissions. Malicious peer!");
                                throw new InvalidStateException();
                            }
                        }
                        else
                        {
                            if ((sender.HeldPermissions & Permission.Unicast) == 0)
                            {
                                Console.WriteLine("Sender does not have unicast permissions. Malicious peer!");
                                throw new InvalidStateException();
                            }
                        }
                    }
                }

                await remoteMerkleTree.ImportAsync(have.MerkleRootHash, nodesToImport).ConfigureAwait(false);

                Console.WriteLine($"Currently have {nodesToImport.Count} nodes to import still");

                foreach (var tuple in nodesToImport)
                {
                    var node = tuple.Item2;
                    if (node.Descendents == 0 && await localMerkleTree.GetNodeAsync(tuple.Item1).ConfigureAwait(false) == null)
                    {
                        var isDataNode = node.TypeTag == MerkleNodeTypeTag.Data;
                        BroadcastMessageDto message = isDataNode ? broadcastMessageSerializer.Deserialize(node.Contents) : null;

                        Console.WriteLine("Got data node");

                        var insertionResult = await localMerkleTree.TryInsertAsync(tuple.Item2).ConfigureAwait(false);

                        if (insertionResult.Item1 && isDataNode)
                        {
                            byte[] decryptedPayload;
                            Console.WriteLine("Got a message");
                            if (identity.TryDecodePayload(message, out decryptedPayload))
                            {
                                BroadcastReceived?.Invoke(new MessageReceivedEventArgs(neighbor, new BroadcastMessage {
                                    SourceId         = IdentityHash.GetFlyweight(message.SourceIdHash),
                                    DestinationId    = IdentityHash.GetFlyweight(message.DestinationIdHash),
                                    DecryptedPayload = decryptedPayload,
                                    Dto = message
                                }));
                            }
                        }
                    }
                }
            }

            DebugPrint("SEND DONE");
            await neighbor.SendAsync(serializer.ToByteArray(new DonePacket())).ConfigureAwait(false);
        }