Exemplo n.º 1
0
        public override Dialog OnCreateDialog(Bundle savedInstanceState)
        {
            base.OnCreateDialog(savedInstanceState);

            AlertDialog.Builder builder = new AlertDialog.Builder(Activity)
                                          .SetView(Resource.Layout.Dialog)
                                          .SetPositiveButton(Resource.String.Join, (sender, e) => {
                var roomName = Dialog.FindViewById <EditText>(Resource.Id.Userinput).Text;

                ChatRoomContext context = Globals.CampfireChatClient.ChatRoomTable.GetOrCreate(IdentityHash.GetFlyweight(CryptoUtil.GetHash(CryptoUtil.GetHash(Encoding.UTF8.GetBytes(roomName)))));
                context.FriendlyName    = roomName;

                Globals.CampfireNetClient.IdentityManager.AddMulticastKey(
                    IdentityHash.GetFlyweight(CryptoUtil.GetHash(CryptoUtil.GetHash(Encoding.UTF8.GetBytes(roomName)))),
                    CryptoUtil.GetHash(Encoding.UTF8.GetBytes(roomName)));

                byte[] roomKey = CryptoUtil.GetHash(CryptoUtil.GetHash(Encoding.UTF8.GetBytes(roomName)));
                Globals.JoinedRooms.Add(roomKey);

                uiHandler.ObtainMessage(0, new ChatEntry(roomKey, context)).SendToTarget();

                Dismiss();
            })
                                          .SetNegativeButton(Resource.String.Cancel, (sender, e) => {
                Dismiss();
            });

            return(builder.Create());
        }
Exemplo n.º 2
0
        public async Task MulticastAsync(IdentityHash destinationId, byte[] payload)
        {
            byte[] symmetricKey;
            if (!identity.IdentityManager.TryLookupMulticastKey(destinationId, out symmetricKey))
            {
                throw new InvalidStateException("Attempted to multicast to destination of unknown key!");
            }

            var messageDto           = identity.EncodePacket(payload, symmetricKey);
            var localInsertionResult = await localMerkleTree.TryInsertAsync(messageDto).ConfigureAwait(false);

            if (localInsertionResult.Item1)
            {
                // "Decrypt the message"
                MessageSent?.Invoke(new MessageReceivedEventArgs(
                                        null,
                                        new BroadcastMessage {
                    SourceId         = IdentityHash.GetFlyweight(identity.PublicIdentityHash),
                    DestinationId    = destinationId,
                    DecryptedPayload = payload,
                    Dto = messageDto
                }
                                        ));
            }
        }
        private static Dictionary <IdentityHash, int> ReadLogicalClock(BinaryReader reader)
        {
            var dict  = new Dictionary <IdentityHash, int>();
            var count = reader.ReadInt32();

            for (var i = 0; i < count; i++)
            {
                var identityHashBytes = reader.ReadBytes(CryptoUtil.HASH_SIZE);
                var clock             = reader.ReadInt32();

                var identityHash = IdentityHash.GetFlyweight(identityHashBytes);
                dict.Add(identityHash, clock);
            }
            return(dict);
        }
Exemplo n.º 4
0
        public async Task BroadcastAsync(byte[] payload)
        {
            var messageDto = identity.EncodePacket(payload, null);

            var localInsertionResult = await localMerkleTree.TryInsertAsync(messageDto).ConfigureAwait(false);

            if (localInsertionResult.Item1)
            {
                // "Decrypt the message"
                MessageSent?.Invoke(new MessageReceivedEventArgs(
                                        null,
                                        new BroadcastMessage {
                    SourceId         = IdentityHash.GetFlyweight(identity.PublicIdentityHash),
                    DestinationId    = IdentityHash.GetFlyweight(Identity.BROADCAST_ID),
                    DecryptedPayload = payload,
                    Dto = messageDto
                }
                                        ));
            }
        }
Exemplo n.º 5
0
        public async Task UnicastAsync(IdentityHash destinationId, byte[] payload)
        {
            var trustChainNode = identity.IdentityManager.LookupIdentity(destinationId.Bytes.ToArray());

            var messageDto           = identity.EncodePacket(payload, trustChainNode.ThisId);
            var localInsertionResult = await localMerkleTree.TryInsertAsync(messageDto).ConfigureAwait(false);

            if (localInsertionResult.Item1)
            {
                // "Decrypt the message"
                MessageSent?.Invoke(new MessageReceivedEventArgs(
                                        null,
                                        new BroadcastMessage {
                    SourceId         = IdentityHash.GetFlyweight(identity.PublicIdentityHash),
                    DestinationId    = destinationId,
                    DecryptedPayload = payload,
                    Dto = messageDto
                }
                                        ));
            }
        }
Exemplo n.º 6
0
        public void Setup()
        {
            Console.WriteLine("Adding data");
            if (Globals.JoinedRooms == null)
            {
                Globals.CampfireChatClient.ChatRoomTable.GetOrCreate(IdentityHash.GetFlyweight(Identity.BROADCAST_ID)).FriendlyName = "Broadcast";
                Globals.CampfireChatClient.ChatRoomTable.GetOrCreate(IdentityHash.GetFlyweight(CryptoUtil.GetHash(CryptoUtil.GetHash(Encoding.UTF8.GetBytes("General"))))).FriendlyName = "General";
                Globals.CampfireChatClient.ChatRoomTable.GetOrCreate(IdentityHash.GetFlyweight(CryptoUtil.GetHash(CryptoUtil.GetHash(Encoding.UTF8.GetBytes("Test"))))).FriendlyName    = "Test";

                Globals.CampfireNetClient.IdentityManager.AddMulticastKey(
                    IdentityHash.GetFlyweight(CryptoUtil.GetHash(CryptoUtil.GetHash(Encoding.UTF8.GetBytes("General")))),
                    CryptoUtil.GetHash(Encoding.UTF8.GetBytes("General")));

                Globals.CampfireNetClient.IdentityManager.AddMulticastKey(
                    IdentityHash.GetFlyweight(CryptoUtil.GetHash(CryptoUtil.GetHash(Encoding.UTF8.GetBytes("Test")))),
                    CryptoUtil.GetHash(Encoding.UTF8.GetBytes("Test")));

                Globals.JoinedRooms = new HashSet <byte[]> {
                    Identity.BROADCAST_ID,
                    CryptoUtil.GetHash(CryptoUtil.GetHash(Encoding.UTF8.GetBytes("General"))),
                    CryptoUtil.GetHash(CryptoUtil.GetHash(Encoding.UTF8.GetBytes("Test"))),
                };
            }
            var testEntries = GetKnownRooms();


            chatlistRecyclerView = (RecyclerView)FindViewById(Resource.Id.ChatList);
            chatlistRecyclerView.HasFixedSize = true;

            chatlistLayoutManager = new LinearLayoutManager(this);
            chatlistRecyclerView.SetLayoutManager(chatlistLayoutManager);

            chatlistAdapter            = new ChatlistAdapter(testEntries);
            chatlistAdapter.ItemClick += OnItemClick;
            chatlistRecyclerView.SetAdapter(chatlistAdapter);
        }
Exemplo n.º 7
0
        public ChatRoomContext ConfigurePublicChatRoom(string name)
        {
            var roomHashBytes = Encoding.UTF8.GetBytes(name);

            return(ChatRoomTable.GetOrCreate(IdentityHash.GetFlyweight(CryptoUtil.GetHash(roomHashBytes))));
        }
Exemplo n.º 8
0
        public ChatRoomViewModel CreateChatRoomViewModelByNameAndSubscribe(string chatroomName, ChatMessageReceivedCallback messageReceivedCallback)
        {
            var destinationHash = IdentityHash.GetFlyweight(CryptoUtil.GetHash(Encoding.UTF8.GetBytes(chatroomName)));

            return(CreateChatRoomViewModelByIdentityHashAndSubscribe(destinationHash, messageReceivedCallback));
        }
Exemplo n.º 9
0
        private List <ChatEntry> GetKnownRooms()
        {
            var entries = new List <ChatEntry>();

            foreach (var roomKey in Globals.JoinedRooms)
            {
                ChatRoomContext context = Globals.CampfireChatClient.ChatRoomTable.GetOrCreate(IdentityHash.GetFlyweight(roomKey));
                entries.Add(new ChatEntry(roomKey, context));
            }

            return(entries);
        }
Exemplo n.º 10
0
        protected override void OnCreate(Bundle savedInstanceState)
        {
            //         testMessages = new List<MessageEntry> {
            //            new MessageEntry("Name 1", "This is a test message 1"),
            //            new MessageEntry("Name 2", "This is a test message 2"),
            //            new MessageEntry("Name 3", "This is a test message 3"),
            //            new MessageEntry("Name 2", "This is a test message 4 really long message here one that is sure to overflow. How about some more text here and see if we can get it to three lines - or even more! How far can we go?"),
            //            new MessageEntry("Name 3", "This is a test message 5"),
            //            new MessageEntry("Name 1", "These are yet more messages designed to be long and take up space."),
            //            new MessageEntry("Name 2", "These are yet more messages designed to be long and take up space."),
            //            new MessageEntry("Name 3", "These are yet more messages designed to be long and take up space."),
            //            new MessageEntry("Name 1", "These are yet more messages designed to be long and take up space."),
            //            new MessageEntry("Name 2", "These are yet more messages designed to be long and take up space.")
            //         };

            base.OnCreate(savedInstanceState);
            SetContentView(Resource.Layout.Chat);

            var toolbar = FindViewById <Android.Widget.Toolbar>(Resource.Id.Toolbar);

            SetActionBar(toolbar);
            ActionBar.SetDisplayHomeAsUpEnabled(true);

            chatRecyclerView = (RecyclerView)FindViewById(Resource.Id.Messages);
            chatRecyclerView.HasFixedSize = true;

            chatLayoutManager = new LinearLayoutManager(this);
            chatRecyclerView.SetLayoutManager(chatLayoutManager);

            chatAdapter            = new ChatAdapter();
            chatAdapter.ItemClick += OnItemClick;
            chatRecyclerView.SetAdapter(chatAdapter);

            var chatId = Intent.GetByteArrayExtra("chatId");

            chatRoomContext = Globals.CampfireChatClient.ChatRoomTable.GetOrCreate(IdentityHash.GetFlyweight(chatId));
            Title           = chatRoomContext.FriendlyName;

            viewModel = chatRoomContext.CreateViewModelAndSubscribe((sender, e) => {
                Console.WriteLine("        ######## hitting add entry time");
                var message = e.Message;
                if (message.ContentType != ChatMessageContentType.Text)
                {
                    throw new NotImplementedException();
                }

                chatAdapter.AddEntry(new MessageEntry(message, message.FriendlySenderName, Encoding.UTF8.GetString(message.ContentRaw)));
                uiHandler.ObtainMessage(UPDATE_VIEW, -1, 0).SendToTarget();
            });
            foreach (var message in viewModel.InitialMessages)
            {
                chatAdapter.AddEntry(new MessageEntry(message, message.FriendlySenderName, Encoding.UTF8.GetString(message.ContentRaw)));
            }

            var sendButton = FindViewById <Button>(Resource.Id.SendMessage);

            sendButton.Click += HandleSendButtonClicked;

            uiHandler = new LambdaHandler(msg => {
                if (msg.What == UPDATE_VIEW)
                {
                    var index = msg.Arg1 == -1 ? chatAdapter.Entries.Count - 1 : msg.Arg1;
                    Console.WriteLine($"Updating item view at {index}");
                    //               chatAdapter.NotifyItemChanged(index);
                    chatAdapter.NotifyDataSetChanged();
                    chatRecyclerView.GetLayoutManager().ScrollToPosition(chatAdapter.Entries.Count - 1);
                }
            });
        }
Exemplo n.º 11
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);
        }