apsun / NekoSMS

A pattern-based text message blocker for Android.
GNU General Public License v3.0
417 stars 44 forks source link

Acknowledge message to the SMSC. #55

Closed komurlu closed 5 years ago

komurlu commented 5 years ago

Does this app sends or blocks acknowledge message to SMSC when an SMS is blocked?

If "storage full" or such a similar error message is sent to SMSC, sender will not receive a successful delivery receipt, so SMS will be blocked completely.

apsun commented 5 years ago

I'm not sure how much of the SMS flow is done by the system; so unfortunately the answer to your question is I don't know.

Are you saying you want delivery receipts to be blocked, or that you want to deliver fake error receipts?

komurlu commented 5 years ago

Even if an SMS is blocked, phone sends network ACK that it received SMS successfully and this causes sender to see SMS as delivered.

I'm trying to find a way to say to the network that phone couldn't handle that last SMS. In this way, sender will not see our blocked SMS as 'successful'.

I'm wondering if black list controls can be done inside dispatchNormalMessage(); and if message is to be blocked, return Intents.RESULT_SMS_UNSUPPORTED. Normally it returns android.provider.Telephony.Sms.Intents.RESULT_SMS_HANDLED which causes sending success ACK to the network.

As beginning comments says

The state machine starts in {@link IdleState} state. When the {@link SMSDispatcher} receives a
new SMS from the radio, it calls {@link #dispatchNormalMessage},

If we return Intents.RESULT_SMS_UNSUPPORTED before normal return in dispatchNormalMessage(); , we'll prevent message to be added to the tables, and send error ACK to radio, and hopefully network will not retry sending this SMS.

apsun commented 5 years ago

Ok, so I took a look at how ACKs are generated, and it seems ACK messages operate on a different level of abstraction from what we currently use. It's kind of like trying to force an arbitrary IP packet through a TCP socket. So it's not impossible, but certainly difficult and would take a lot of work.

The main problem is that dispatchNormalMessage operates on single message "fragments", while dispatchIntent operates on the entire re-assembled message. In high-level pseudocode, it's something like (state machine stuff omitted for brevity):

message = "";
while (haveMoreMessageParts()) {
    dispatchNormalMessage(); // message += <next part>
    sendAckForPart();
}
dispatchIntent(message);

You might ask, why not just hook dispatchNormalMessage instead? The problem is that dispatchNormalMessage does not see the entire message, but NekoSMS filters work on the entire re-assembled message. So you would somehow need to go back in time to prevent the ACKs from being sent. Alternatively, you could do some insane hooking where you enqueue the ACKs until after the entire message has been received and filtered, then send the correct ACK for all messages in the queue. Not impossible, but definitely a challenge.

So unfortunately, I think this is out of scope for this project (or at least, the amount of time I have).