Пример #1
0
        public void ReceiveCallback(IAsyncResult result)
        {
            try
            {
                // Check how much bytes are received and call EndReceive to finalize handshake
                var received = Tcp.Client.EndReceive(result);

                // If we have received nothing then leave.
                if (received <= 0)
                {
                    return;
                }

                // Copy the recieved data into new buffer , to avoid null bytes
                var recData = new byte[received];
                Buffer.BlockCopy(ReceiveBuffer, 0, recData, 0, received);

                var encryptedString = Encoding.UTF8.GetString(recData);

                WholeMessage = string.IsNullOrWhiteSpace(WholeMessage)
                        ? encryptedString
                        : WholeMessage + encryptedString;

                // This is the reply to the start of the interaction.
                // If we can decrypt here, then we send back the _sym
                // key we will be using to encrypt our messages.
                if (WholeMessage.EndsWith("<BEG>"))
                {
                    WholeMessage = WholeMessage.Replace("<BEG>", "");
                    var decryptedString = Crypto.DecryptWithAesKeyIV(WholeMessage, Crypto.CreateAesKeyIV(_sharedPasscode));
                    var publicKey       = PublicKey.FromJson(new JSONObject(decryptedString));

                    // Send a new AES Symmetric key for using!
                    _sharedSymmetricKey = Crypto.CreateAesKeyIV();
                    var encryptedWithTheirPublicKey = Crypto.EncryptWithPublicKey(
                        publicKey.ToRsaParameters(), System.Text.Encoding.UTF8.GetBytes(_sharedSymmetricKey.ToJson().ToString()));
                    Task.Run(async() => await StartConversation(Convert.ToBase64String(encryptedWithTheirPublicKey) + "<END>"));

                    WholeMessage = null;
                }
                else if (WholeMessage.EndsWith("<TAC>"))
                {
                    // The computer asked for the client list...
                    // we shall send it to them encrypted!
                    var contacts  = Contact.GetAllContacts(this);
                    var jsonArray = ContactInfo.ToJsonArray(contacts);
                    var encrypted = Crypto.EncryptWithAesKeyIV(jsonArray.ToString(), _sharedSymmetricKey);
                    var msg       = Encoding.UTF8.GetBytes(encrypted + "<TAC>");
                    Task.Run(async() => await Tcp.Client.SendAsync(new ArraySegment <byte>(msg), SocketFlags.None));

                    WholeMessage = null;
                }
                else if (WholeMessage.EndsWith("<EOF>"))
                {
                    // This is an encrypted message from the computer.
                    WholeMessage = WholeMessage.Replace("<EOF>", "");
                    var decryptedString = Crypto.DecryptWithAesKeyIV(WholeMessage, _sharedSymmetricKey);
                    var payload         = TcpPayload.FromJson(new JSONObject(decryptedString));

                    if (!string.IsNullOrWhiteSpace(payload.Contact.PhoneNumber) &&
                        !string.IsNullOrWhiteSpace(payload.Message))
                    {
                        // TODO Possible send delay so we don't  overload the sms manager?
                        Sms.SendTo(payload.Contact.PhoneNumber, payload.Message);
                    }
                    else
                    {
                        // Log an issue...
                    }

                    WholeMessage = null;
                }

                // Start receiving again
                Tcp.Client.BeginReceive(ReceiveBuffer, 0, ReceiveBuffer.Length,
                                        SocketFlags.None, ReceiveCallback, null);
            }
            catch (SocketException ex)
            {
                Android.Util.Log.Error("Receive Callback", ex.Message);
                OnDestroy();
            }
            catch (Exception ex)
            {
                Android.Util.Log.Error("Receive Callback", ex.Message);

                // Clear the whole message
                WholeMessage = null;

                // Start receiving again
                if (Tcp != null && Tcp.Client != null)
                {
                    Tcp.Client.BeginReceive(ReceiveBuffer, 0, ReceiveBuffer.Length,
                                            SocketFlags.None, ReceiveCallback, null);
                }
            }
        }
Пример #2
0
        // TODO investigate and ensure that a single receive will
        // only ever come from 1 source and not multiple sources like
        // the pdusObj might suggest.
        public override void OnReceive(Context context, Intent intent)
        {
            // If we don't have a connection we aren't storing messages
            // to send at a later date, so just jump out.
            if (!TcpService.HasTcpConnection)
            {
                return;
            }

            // Retrieves a map of extended data from the intent.
            var bundle = intent.Extras;

            try
            {
                if (bundle != null)
                {
                    var pdusObj    = (Java.Lang.Object[])bundle.Get("pdus");
                    var tcpPayload = new TcpPayload
                    {
                        Contact = new ContactInfo {
                            ID = "-1", PhoneNumber = null, Name = null
                        },
                        Message = ""
                    };

                    foreach (var t in pdusObj)
                    {
                        var currentMessage = SmsMessage.CreateFromPdu((byte[])t, bundle.GetString("format"));
                        var phoneNumber    = currentMessage.DisplayOriginatingAddress;
                        var message        = currentMessage.DisplayMessageBody;

                        if (tcpPayload.Contact.PhoneNumber != null)
                        {
                            // We already have the phone number so just append the message.
                            tcpPayload.Message += message;
                        }
                        else
                        {
                            // We possibly could find multiple contacts with the same
                            // phone number. The app does nothing to stop this.
                            var contacts = Contact.FindContact(phoneNumber, context);


                            if (contacts.Count >= 1)
                            {
                                // If we only have 1 contact show that name.
                                tcpPayload.Contact = contacts[0];
                            }
                            else
                            {
                                // Otherwise we no contact so just put the phone number in.
                                tcpPayload.Contact.PhoneNumber = phoneNumber;
                            }

                            tcpPayload.Message = message;
                        }
                    }

                    if (tcpPayload.Contact.PhoneNumber != null &&
                        !string.IsNullOrWhiteSpace(tcpPayload.Message))
                    {
                        var outgoingIntent = new Intent(context, typeof(TcpService));
                        outgoingIntent.SetAction(TcpService.ACTION_SEND_MESSAGE);
                        outgoingIntent.PutExtra("payload", tcpPayload.ToJson().ToString());
                        context.StartService(outgoingIntent);
                    }
                    else
                    {
                        throw new Exception($"We parsed the message, but something when wrong. Phone Number: {tcpPayload.Contact.PhoneNumber}. Message: {tcpPayload.Message}.");
                    }
                }
            }
            catch (Exception ex)
            {
                Android.Util.Log.Error("SMS_READ", ex.Message);
            }
        }