session-android/src/org/thoughtcrime/securesms/sms/MultipartSmsMessageHandler.java
Moxie Marlinspike 19dddd7adf Support for an 'end session' protocol message.
1) On the push side, this message is a flag in PushMessageContent.
   Any secure message with that flag will terminate the current
   sessin.

2) On the SMS side, there is an "end session" wire type and
   the convention that a message with this wire type must be
   secure and contain the string "TERMINATE."
2014-02-19 13:50:32 -08:00

99 lines
4.5 KiB
Java

/**
* Copyright (C) 2011 Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms.sms;
import android.util.Log;
import org.whispersystems.textsecure.util.Base64;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
public class MultipartSmsMessageHandler {
private final HashMap<String, MultipartSmsTransportMessageFragments> partialMessages =
new HashMap<String, MultipartSmsTransportMessageFragments>();
private IncomingTextMessage processMultipartMessage(MultipartSmsTransportMessage message) {
Log.w("MultipartSmsMessageHandler", "Processing multipart message...");
Log.w("MultipartSmsMessageHandler", "Multipart Count: " + message.getMultipartCount());
Log.w("MultipartSmsMessageHandler", "Multipart ID: " + message.getIdentifier());
Log.w("MultipartSmsMessageHandler", "Multipart Key: " + message.getKey());
MultipartSmsTransportMessageFragments container = partialMessages.get(message.getKey());
Log.w("MultipartSmsMessageHandler", "Found multipart container: " + container);
if (container == null || container.getSize() != message.getMultipartCount() || container.isExpired()) {
Log.w("MultipartSmsMessageHandler", "Constructing new container...");
container = new MultipartSmsTransportMessageFragments(message.getMultipartCount());
partialMessages.put(message.getKey(), container);
}
container.add(message);
Log.w("MultipartSmsMessageHandler", "Filled buffer at index: " + message.getMultipartIndex());
if (!container.isComplete())
return null;
partialMessages.remove(message.getKey());
String strippedMessage = Base64.encodeBytesWithoutPadding(container.getJoined());
if (message.getWireType() == MultipartSmsTransportMessage.WIRETYPE_KEY) {
return new IncomingKeyExchangeMessage(message.getBaseMessage(), strippedMessage);
} else if (message.getWireType() == MultipartSmsTransportMessage.WIRETYPE_PREKEY) {
return new IncomingPreKeyBundleMessage(message.getBaseMessage(), strippedMessage);
} else {
return new IncomingEncryptedMessage(message.getBaseMessage(), strippedMessage);
}
}
private IncomingTextMessage processSinglePartMessage(MultipartSmsTransportMessage message) {
Log.w("MultipartSmsMessageHandler", "Processing single part message...");
String strippedMessage = Base64.encodeBytesWithoutPadding(message.getStrippedMessage());
if (message.getWireType() == MultipartSmsTransportMessage.WIRETYPE_KEY) {
return new IncomingKeyExchangeMessage(message.getBaseMessage(), strippedMessage);
} else if (message.getWireType() == MultipartSmsTransportMessage.WIRETYPE_PREKEY) {
return new IncomingPreKeyBundleMessage(message.getBaseMessage(), strippedMessage);
} else if (message.getWireType() == MultipartSmsTransportMessage.WIRETYPE_END_SESSION) {
return new IncomingEndSessionMessage(message.getBaseMessage(), strippedMessage);
} else {
return new IncomingEncryptedMessage(message.getBaseMessage(), strippedMessage);
}
}
public IncomingTextMessage processPotentialMultipartMessage(IncomingTextMessage message) {
try {
MultipartSmsTransportMessage transportMessage = new MultipartSmsTransportMessage(message);
if (transportMessage.isInvalid()) return message;
else if (transportMessage.isSinglePart()) return processSinglePartMessage(transportMessage);
else return processMultipartMessage(transportMessage);
} catch (IOException e) {
Log.w("MultipartSmsMessageHandler", e);
return message;
}
}
public ArrayList<String> divideMessage(OutgoingTextMessage message) {
String number = message.getRecipients().getPrimaryRecipient().getNumber();
byte identifier = MultipartSmsIdentifier.getInstance().getIdForRecipient(number);
return MultipartSmsTransportMessage.getEncoded(message, identifier);
}
}