public void onSend(string str)
        {
            if (str.Length < 1)
            {
                return;
            }

            // TODOSPIXI

            /*            // Send the message to the S2 nodes
             *          byte[] recipient_address = friend.wallet_address;
             *          byte[] encrypted_message = StreamProcessor.prepareSpixiMessage(SpixiMessageCode.chat, str, friend.pubkey);
             *          // CryptoManager.lib.encryptData(Encoding.UTF8.GetBytes(string_to_send), friend.pubkey);
             *
             *          // Check the relay ip
             *          string relayip = friend.getRelayIP();
             *          if (relayip == null)
             *          {
             *              Logging.warn("No relay node to send message to!");
             *              return;
             *          }
             *          if (relayip.Equals(node_ip, StringComparison.Ordinal) == false)
             *          {
             *
             *              node_ip = relayip;
             *              // Connect to the contact's S2 relay first
             *              NetworkClientManager.connectToStreamNode(relayip);
             *
             *              // TODO: optimize this
             *              while (NetworkClientManager.isNodeConnected(relayip) == false)
             *              {
             *
             *              }
             *          }
             *
             *          Message message = new Message();
             *          message.recipientAddress = recipient_address;
             *          message.data = encrypted_message;
             *
             *          StreamProcessor.sendMessage(message, node_ip);*/

            SpixiMessage spixi_message = new SpixiMessage(SpixiMessageCode.chat, Encoding.UTF8.GetBytes(str));


            StreamMessage message = new StreamMessage();

            message.type        = StreamMessageCode.data;
            message.recipient   = friend.walletAddress;
            message.sender      = Node.walletStorage.getPrimaryAddress();
            message.transaction = new byte[1];
            message.sigdata     = new byte[1];
            message.data        = spixi_message.getBytes();

            string relayip = friend.searchForRelay();

            StreamProcessor.sendMessage(message, relayip);

            // Finally, add the text bubble visually
            DateTime      dt  = DateTime.Now;
            FriendMessage msg = new FriendMessage(str, String.Format("{0:t}", dt), false);

            friend.messages.Add(msg);
            insertMessage(msg);

            // Finally, clear the input field
            webView.Eval("clearInput()");
        }
Example #2
0
        public static bool sendFileData(Friend friend, string uid, ulong packet_number)
        {
            FileTransfer transfer = TransferManager.getOutgoingTransfer(uid);

            if (transfer == null)
            {
                return(false);
            }



            using (MemoryStream m = new MemoryStream())
            {
                using (BinaryWriter writer = new BinaryWriter(m))
                {
                    writer.Write(uid);

                    writer.Write(packet_number);

                    Logging.info("Sending file packet #{0}", packet_number);
                    byte[] data = transfer.getPacketData(packet_number);

                    // Write the data
                    if (data != null)
                    {
                        writer.Write(data.Length);
                        writer.Write(data);
                    }
                    else
                    {
                        writer.Write(0);
                    }
                }

                SpixiMessage spixi_message = new SpixiMessage(SpixiMessageCode.fileData, m.ToArray());


                StreamMessage message = new StreamMessage();
                message.type        = StreamMessageCode.data;
                message.recipient   = friend.walletAddress;
                message.sender      = Node.walletStorage.getPrimaryAddress();
                message.transaction = new byte[1];
                message.sigdata     = new byte[1];
                message.data        = spixi_message.getBytes();

                StreamProcessor.sendMessage(friend, message, false, false, false);
            }

            if (friend.chat_page != null)
            {
                ulong totalPackets = transfer.fileSize / (ulong)transfer.packetSize;
                ulong fp           = 0;
                bool  complete     = false;
                if (totalPackets == packet_number)
                {
                    fp       = 100;
                    complete = true;
                }
                else
                {
                    fp = packet_number * 100 / totalPackets;
                }

                friend.chat_page.updateFile(uid, fp.ToString(), complete);
            }

            return(true);
        }
Example #3
0
        // Called when an encryption key is received from the S2 server, as per step 4 of the WhitePaper

        /*private static void sendRsaEncryptedMessage(StreamMessage msg, string key, RemoteEndpoint endpoint)
         * {
         * // TODO TODO use transaction code for S2
         *  using (MemoryStream m = new MemoryStream())
         *  {
         *      using (BinaryWriter writer = new BinaryWriter(m))
         *      {
         *          writer.Write(msg.getID());
         *          writer.Write(msg.recipientAddress);
         *          writer.Write(msg.transactionID);
         *      }
         *  }
         *  Console.WriteLine("Sending encrypted message with key {0}", key);
         *
         *          using (MemoryStream m = new MemoryStream())
         *          {
         *              using (BinaryWriter writer = new BinaryWriter(m))
         *              {
         *                  writer.Write(msg.getID());
         *                  writer.Write(msg.recipientAddress);
         *                  writer.Write(msg.transactionID);
         *
         *                  byte[] encrypted_message = CryptoManager.lib.encryptDataS2(msg.data, key);
         *                  int encrypted_count = encrypted_message.Count();
         *
         *                  writer.Write(encrypted_count);
         *                  writer.Write(encrypted_message);
         *
         *                  byte[] ba = ProtocolMessage.prepareProtocolMessage(ProtocolMessageCode.s2data, m.ToArray());
         *                  socket.Send(ba, SocketFlags.None);
         *
         *
         *                  // Update the DLT transaction as well
         *                  Transaction transaction = new Transaction(0, msg.recipientAddress, Node.walletStorage.address);
         *                  transaction.id = msg.transactionID;
         *                  //transaction.data = Encoding.UTF8.GetString(checksum);
         *                  //ProtocolMessage.broadcastProtocolMessage(ProtocolMessageCode.updateTransaction, transaction.getBytes());
         *
         *              }
         *          }
         * }*/

        // Called when receiving S2 data from clients
        public static void receiveData(byte[] bytes, RemoteEndpoint endpoint)
        {
            StreamMessage message = new StreamMessage(bytes);

            if (message.data == null)
            {
                Logging.error(string.Format("Null message data."));
                return;
            }

            Logging.info("Received S2 data from {0} for {1}", Base58Check.Base58CheckEncoding.EncodePlain(message.sender), Base58Check.Base58CheckEncoding.EncodePlain(message.recipient));

            Friend friend = null;

            // decrypt the message if necessary
            // TODO TODO TODO add message receive queue for when the keys aren't available yet
            if (message.encryptionType != StreamMessageEncryptionCode.none)
            {
                byte[] aes_key    = null;
                byte[] chacha_key = null;

                friend = FriendList.getFriend(message.sender);
                if (friend != null)
                {
                    aes_key    = friend.aesKey;
                    chacha_key = friend.chachaKey;
                }
                if (!message.decrypt(Node.walletStorage.getPrimaryPrivateKey(), aes_key, chacha_key))
                {
                    Logging.error("Could not decrypt message from {0}", Base58Check.Base58CheckEncoding.EncodePlain(friend.walletAddress));
                    return;
                }
            }

            // Extract the Spixi message
            SpixiMessage spixi_message = new SpixiMessage(message.data);

            switch (spixi_message.type)
            {
            case SpixiMessageCode.chat:
            {
                // Add the message to the friend list
                FriendList.addMessage(spixi_message.id, message.sender, Encoding.UTF8.GetString(spixi_message.data));
            }
            break;

            case SpixiMessageCode.getNick:
            {
                // Send the nickname to the sender as requested
                handleGetNick(message.sender, Encoding.UTF8.GetString(spixi_message.data));
            }
            break;

            case SpixiMessageCode.nick:
            {
                // Set the nickname for the corresponding address
                if (spixi_message.data != null)
                {
                    FriendList.setNickname(message.sender, Encoding.UTF8.GetString(spixi_message.data));
                }
                else
                {
                    FriendList.setNickname(message.sender, Base58Check.Base58CheckEncoding.EncodePlain(message.sender));
                }
            }
            break;

            case SpixiMessageCode.requestAdd:
            {
                // Friend request
                handleRequestAdd(spixi_message.id, message.sender, spixi_message.data);
            }
            break;

            case SpixiMessageCode.acceptAdd:
            {
                // Friend accepted request
                handleAcceptAdd(message.sender, spixi_message.data);
            }
            break;

            case SpixiMessageCode.sentFunds:
            {
                // Friend requested funds
                handleSentFunds(spixi_message.id, message.sender, Encoding.UTF8.GetString(spixi_message.data));
            }
            break;

            case SpixiMessageCode.requestFunds:
            {
                // Friend requested funds
                handleRequestFunds(spixi_message.id, message.sender, Encoding.UTF8.GetString(spixi_message.data));
            }
            break;

            case SpixiMessageCode.requestFundsResponse:
            {
                handleRequestFundsResponse(spixi_message.id, message.sender, Encoding.UTF8.GetString(spixi_message.data));
            }
            break;

            case SpixiMessageCode.keys:
            {
                handleReceivedKeys(message.sender, spixi_message.data);
            }
            break;

            case SpixiMessageCode.msgReceived:
            {
                handleMsgReceived(message.sender, spixi_message);
                // don't send confirmation back, so just return
                return;
            }

            case SpixiMessageCode.msgRead:
            {
                handleMsgRead(message.sender, spixi_message);
                // don't send confirmation back, so just return
                return;
            }

            case SpixiMessageCode.fileHeader:
            {
                handleFileHeader(message.sender, spixi_message);
            }
            break;
            }

            if (friend == null)
            {
                friend = FriendList.getFriend(message.sender);
            }

            if (friend == null)
            {
                Logging.error("Cannot send received confirmation, friend is null");
                return;
            }

            // Send received confirmation
            StreamMessage msg_received = new StreamMessage();

            msg_received.type           = StreamMessageCode.info;
            msg_received.sender         = IxianHandler.getWalletStorage().getPrimaryAddress();
            msg_received.recipient      = message.sender;
            msg_received.data           = new SpixiMessage(spixi_message.id, SpixiMessageCode.msgReceived, null).getBytes();
            msg_received.transaction    = new byte[1];
            msg_received.sigdata        = new byte[1];
            msg_received.encryptionType = StreamMessageEncryptionCode.none;

            sendMessage(friend, msg_received, true);
        }
Example #4
0
        // Send an encrypted message using the S2 network
        public static bool sendMessage(Friend friend, StreamMessage msg, bool add_to_offline_messages = true)
        {
            // TODO this function has to be improved and node's wallet address has to be added


            string hostname = friend.searchForRelay();

            if (friend.publicKey != null && (msg.encryptionType == StreamMessageEncryptionCode.rsa || (friend.aesKey != null && friend.chachaKey != null)))
            {
                msg.encrypt(friend.publicKey, friend.aesKey, friend.chachaKey);
            }
            else if (msg.encryptionType != StreamMessageEncryptionCode.none || !friend.online)
            {
                if (friend.publicKey == null)
                {
                    byte[] pub_k = FriendList.findContactPubkey(friend.walletAddress);
                    friend.publicKey = pub_k;
                }



                StreamClientManager.connectTo(hostname, null); // TODO replace null with node address
                Logging.warn("Could not send message to {0}, due to missing encryption keys, adding to offline queue!", Base58Check.Base58CheckEncoding.EncodePlain(msg.recipient));
                if (add_to_offline_messages)
                {
                    addOfflineMessage(msg);
                }
                return(false);
            }

            if (!StreamClientManager.sendToClient(hostname, ProtocolMessageCode.s2data, msg.getBytes(), Encoding.UTF8.GetBytes(msg.getID())))
            {
                StreamClientManager.connectTo(hostname, null); // TODO replace null with node address
                Logging.warn("Could not send message to {0}, adding to offline queue!", Base58Check.Base58CheckEncoding.EncodePlain(msg.recipient));
                if (add_to_offline_messages)
                {
                    addOfflineMessage(msg);
                }
                return(false);
            }

            return(true);

            /*         string pub_k = FriendList.findContactPubkey(msg.recipientAddress);
             *       if (pub_k.Length < 1)
             *       {
             *           Console.WriteLine("Contact {0} not found, adding to offline queue!", msg.recipientAddress);
             *           addOfflineMessage(msg);
             *           return;
             *       }
             *
             *
             *       // Create a new IXIAN transaction
             *       //  byte[] checksum = Crypto.sha256(encrypted_message);
             *       Transaction transaction = new Transaction(0, msg.recipientAddress, Node.walletStorage.address);
             *       //  transaction.data = Encoding.UTF8.GetString(checksum);
             *       msg.transactionID = transaction.id;
             *       //ProtocolMessage.broadcastProtocolMessage(ProtocolMessageCode.newTransaction, transaction.getBytes());
             *
             *       // Add message to the queue
             *       messages.Add(msg);
             *
             *       // Request a new keypair from the S2 Node
             *       if(hostname == null)
             *           ProtocolMessage.broadcastProtocolMessage(ProtocolMessageCode.s2generateKeys, Encoding.UTF8.GetBytes(msg.getID()));
             *       else
             *       {
             *           NetworkClientManager.sendData(ProtocolMessageCode.s2generateKeys, Encoding.UTF8.GetBytes(msg.getID()), hostname);
             *       }*/
        }
Example #5
0
        public async Task onSendFile()
        {
            // Show file picker and send the file
            try
            {
                Stream stream   = null;
                string fileName = null;
                string filePath = null;

                // Special case for iOS platform
                if (Device.RuntimePlatform == Device.iOS)
                {
                    var picker_service = DependencyService.Get <IPicturePicker>();

                    SpixiImageData spixi_img_data = await picker_service.PickImageAsync();

                    stream = spixi_img_data.stream;

                    if (stream == null)
                    {
                        return;
                    }

                    fileName = spixi_img_data.name;
                    filePath = spixi_img_data.path;
                }
                else
                {
                    FileData fileData = await CrossFilePicker.Current.PickFile();

                    if (fileData == null)
                    {
                        return; // User canceled file picking
                    }
                    stream = fileData.GetStream();

                    fileName = fileData.FileName;
                    filePath = fileData.FilePath;
                }

                FileTransfer transfer = TransferManager.prepareFileTransfer(fileName, stream, filePath);
                Logging.info("File Transfer uid: " + transfer.uid);

                SpixiMessage spixi_message = new SpixiMessage(SpixiMessageCode.fileHeader, transfer.getBytes());

                StreamMessage message = new StreamMessage();
                message.type        = StreamMessageCode.data;
                message.recipient   = friend.walletAddress;
                message.sender      = Node.walletStorage.getPrimaryAddress();
                message.transaction = new byte[1];
                message.sigdata     = new byte[1];
                message.data        = spixi_message.getBytes();

                StreamProcessor.sendMessage(friend, message);


                string message_data = string.Format("{0}:{1}", transfer.uid, transfer.fileName);

                // store the message and display it
                FriendMessage friend_message = FriendList.addMessageWithType(message.id, FriendMessageType.fileHeader, friend.walletAddress, message_data, true);

                friend_message.transferId = transfer.uid;
                friend_message.filePath   = transfer.filePath;

                Node.localStorage.writeMessages(friend.walletAddress, friend.messages);
            }
            catch (Exception ex)
            {
                Logging.error("Exception choosing file: " + ex.ToString());
            }
        }
Example #6
0
        public async void onSend(string str)
        {
            if (str.Length < 1)
            {
                return;
            }

            await Task.Run(() =>
            {
                // TODOSPIXI

                /*            // Send the message to the S2 nodes
                 *          byte[] recipient_address = friend.wallet_address;
                 *          byte[] encrypted_message = StreamProcessor.prepareSpixiMessage(SpixiMessageCode.chat, str, friend.pubkey);
                 *          // CryptoManager.lib.encryptData(Encoding.UTF8.GetBytes(string_to_send), friend.pubkey);
                 *
                 *          // Check the relay ip
                 *          string relayip = friend.getRelayIP();
                 *          if (relayip == null)
                 *          {
                 *              Logging.warn("No relay node to send message to!");
                 *              return;
                 *          }
                 *          if (relayip.Equals(node_ip, StringComparison.Ordinal) == false)
                 *          {
                 *
                 *              node_ip = relayip;
                 *              // Connect to the contact's S2 relay first
                 *              NetworkClientManager.connectToStreamNode(relayip);
                 *
                 *              // TODO: optimize this
                 *              while (NetworkClientManager.isNodeConnected(relayip) == false)
                 *              {
                 *
                 *              }
                 *          }
                 *
                 *          Message message = new Message();
                 *          message.recipientAddress = recipient_address;
                 *          message.data = encrypted_message;
                 *
                 *          StreamProcessor.sendMessage(message, node_ip);*/

                // store the message and display it
                FriendMessage friend_message = FriendList.addMessageWithType(null, FriendMessageType.standard, friend.walletAddress, str, true);

                // Finally, clear the input field
                Utils.sendUiCommand(webView, "clearInput");

                // Send the message
                SpixiMessage spixi_message = new SpixiMessage(SpixiMessageCode.chat, Encoding.UTF8.GetBytes(str));

                StreamMessage message = new StreamMessage();
                message.type          = StreamMessageCode.data;
                message.recipient     = friend.walletAddress;
                message.sender        = Node.walletStorage.getPrimaryAddress();
                message.transaction   = new byte[1];
                message.sigdata       = new byte[1];
                message.data          = spixi_message.getBytes();
                message.id            = friend_message.id;

                if (friend.bot)
                {
                    message.encryptionType = StreamMessageEncryptionCode.none;
                    message.sign(IxianHandler.getWalletStorage().getPrimaryPrivateKey());
                }

                StreamProcessor.sendMessage(friend, message);
            });
        }
        public void insertMessage(FriendMessage message)
        {
            if (friend.approved == false)
            {
                if (message.type == FriendMessageType.requestAdd)
                {
                    // Call webview methods on the main UI thread only
                    Utils.sendUiCommand(webView, "showContactRequest", "1");
                    message.read = true;
                    return;
                }
            }
            else
            {
                // Don't show if the friend is already approved
                if (message.type == FriendMessageType.requestAdd)
                {
                    return;
                }
            }

            string prefix = "addMe";
            string avatar = "";//Node.localStorage.getOwnAvatarPath();

            if (!message.localSender)
            {
                prefix = "addThem";
                avatar = "img/spixiavatar.png";
            }

            if (message.type == FriendMessageType.requestFunds)
            {
                string status      = "PENDING";
                string status_icon = "fa-clock";

                string amount = message.message;

                if (message.message.StartsWith("::"))
                {
                    status      = "DECLINED";
                    status_icon = "fa-exclamation-circle";
                    amount      = message.message.Substring(2);
                }
                else if (message.message.StartsWith(":"))
                {
                    Transaction transaction = TransactionCache.getTransaction(message.message.Substring(1));
                    if (transaction == null)
                    {
                        transaction = TransactionCache.getUnconfirmedTransaction(message.message.Substring(1));
                    }

                    amount = "?";

                    if (transaction != null)
                    {
                        amount = transaction.amount.ToString();

                        if (transaction.applied > 0)
                        {
                            status      = "CONFIRMED";
                            status_icon = "fa-check-circle";
                        }
                    }
                }


                if (message.localSender)
                {
                    Utils.sendUiCommand(webView, "addPaymentRequest", Crypto.hashToString(message.id), avatar, "Payment request SENT", amount, status, status_icon, Clock.getRelativeTime(message.timestamp), message.localSender.ToString());
                }
                else
                {
                    Utils.sendUiCommand(webView, "addPaymentRequest", Crypto.hashToString(message.id), avatar, "Payment request RECEIVED", amount, status, status_icon, Clock.getRelativeTime(message.timestamp));
                }
                message.read = true;
                return;
            }

            if (message.type == FriendMessageType.sentFunds)
            {
                message.read = true;
                Transaction transaction = TransactionCache.getTransaction(message.message);
                if (transaction == null)
                {
                    transaction = TransactionCache.getUnconfirmedTransaction(message.message);
                }

                string status      = "PENDING";
                string status_icon = "fa-clock";

                string amount = "?";

                if (transaction != null)
                {
                    if (transaction.applied > 0)
                    {
                        status      = "CONFIRMED";
                        status_icon = "fa-check-circle";
                    }
                    amount = transaction.amount.ToString();
                }

                // Call webview methods on the main UI thread only
                if (message.localSender)
                {
                    Utils.sendUiCommand(webView, "addPaymentRequest", Crypto.hashToString(message.id), avatar, "Payment SENT", amount, status, status_icon, Clock.getRelativeTime(message.timestamp), message.localSender.ToString());
                }
                else
                {
                    Utils.sendUiCommand(webView, "addPaymentRequest", Crypto.hashToString(message.id), avatar, "Payment RECEIVED", amount, status, status_icon, Clock.getRelativeTime(message.timestamp));
                }

                return;
            }


            if (message.type == FriendMessageType.fileHeader)
            {
                prefix = "addFile";
            }

            // Call webview methods on the main UI thread only
            Utils.sendUiCommand(webView, prefix, Crypto.hashToString(message.id), avatar, message.message, Clock.getRelativeTime(message.timestamp), message.confirmed.ToString(), message.read.ToString());

            if (!message.read && !message.localSender)
            {
                message.read = true;
                Node.localStorage.writeMessagesFile(friend.walletAddress, friend.messages);

                // Send read confirmation
                StreamMessage msg_received = new StreamMessage();
                msg_received.type           = StreamMessageCode.info;
                msg_received.sender         = IxianHandler.getWalletStorage().getPrimaryAddress();
                msg_received.recipient      = friend.walletAddress;
                msg_received.data           = new SpixiMessage(message.id, SpixiMessageCode.msgRead, null).getBytes();
                msg_received.transaction    = new byte[1];
                msg_received.sigdata        = new byte[1];
                msg_received.encryptionType = StreamMessageEncryptionCode.none;

                StreamProcessor.sendMessage(friend, msg_received, true);
            }
        }