mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-25 09:17:44 +00:00
use IPv6 routing API then fallback to Lollipop
1) Utilize the hidden API requestRouteToHostAddress that takes an InetAddress (IPv6-capable) instead of a forced IPv4 integer- encoded address. Will fallback to the IPv4 one if reflection fails for whatever reason. 2) If on Lollipop and our manual MMS code doesn't work, will try to use the Lollipop API and give it 60 seconds instead of 30, since I did run into the timeout not being long enough in certain conditions and I'm thinking maybe it just wasn't long enough for some carriers. Closes #3105 // FREEBIE
This commit is contained in:
parent
b354825150
commit
ab82ff0b69
@ -12,6 +12,7 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
|
|||||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||||
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
||||||
import org.thoughtcrime.securesms.mms.ApnUnavailableException;
|
import org.thoughtcrime.securesms.mms.ApnUnavailableException;
|
||||||
|
import org.thoughtcrime.securesms.mms.CompatMmsConnection;
|
||||||
import org.thoughtcrime.securesms.mms.IncomingLollipopMmsConnection;
|
import org.thoughtcrime.securesms.mms.IncomingLollipopMmsConnection;
|
||||||
import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
|
import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
|
||||||
import org.thoughtcrime.securesms.mms.IncomingLegacyMmsConnection;
|
import org.thoughtcrime.securesms.mms.IncomingLegacyMmsConnection;
|
||||||
@ -89,7 +90,7 @@ public class MmsDownloadJob extends MasterSecretJob {
|
|||||||
|
|
||||||
Log.w(TAG, "Downloading mms at " + Uri.parse(contentLocation).getHost());
|
Log.w(TAG, "Downloading mms at " + Uri.parse(contentLocation).getHost());
|
||||||
|
|
||||||
RetrieveConf retrieveConf = getMmsConnection(context).retrieve(contentLocation, transactionId);
|
RetrieveConf retrieveConf = new CompatMmsConnection(context).retrieve(contentLocation, transactionId);
|
||||||
if (retrieveConf == null) {
|
if (retrieveConf == null) {
|
||||||
throw new MmsException("RetrieveConf was null");
|
throw new MmsException("RetrieveConf was null");
|
||||||
}
|
}
|
||||||
@ -123,16 +124,6 @@ public class MmsDownloadJob extends MasterSecretJob {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IncomingMmsConnection getMmsConnection(Context context)
|
|
||||||
throws ApnUnavailableException
|
|
||||||
{
|
|
||||||
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
|
|
||||||
return new IncomingLollipopMmsConnection(context);
|
|
||||||
} else {
|
|
||||||
return new IncomingLegacyMmsConnection(context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCanceled() {
|
public void onCanceled() {
|
||||||
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
||||||
|
@ -11,6 +11,7 @@ import org.thoughtcrime.securesms.database.MmsDatabase;
|
|||||||
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
||||||
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
||||||
import org.thoughtcrime.securesms.mms.ApnUnavailableException;
|
import org.thoughtcrime.securesms.mms.ApnUnavailableException;
|
||||||
|
import org.thoughtcrime.securesms.mms.CompatMmsConnection;
|
||||||
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
||||||
import org.thoughtcrime.securesms.mms.MmsSendResult;
|
import org.thoughtcrime.securesms.mms.MmsSendResult;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingLegacyMmsConnection;
|
import org.thoughtcrime.securesms.mms.OutgoingLegacyMmsConnection;
|
||||||
@ -68,11 +69,11 @@ public class MmsSendJob extends SendJob {
|
|||||||
validateDestinations(message);
|
validateDestinations(message);
|
||||||
|
|
||||||
final byte[] pduBytes = getPduBytes(masterSecret, message);
|
final byte[] pduBytes = getPduBytes(masterSecret, message);
|
||||||
final SendConf sendConf = getMmsConnection(context).send(pduBytes);
|
final SendConf sendConf = new CompatMmsConnection(context).send(pduBytes);
|
||||||
final MmsSendResult result = getSendResult(sendConf, message);
|
final MmsSendResult result = getSendResult(sendConf, message);
|
||||||
|
|
||||||
database.markAsSent(messageId, result.getMessageId(), result.getResponseStatus());
|
database.markAsSent(messageId, result.getMessageId(), result.getResponseStatus());
|
||||||
} catch (UndeliverableMessageException | IOException | ApnUnavailableException e) {
|
} catch (UndeliverableMessageException | IOException e) {
|
||||||
Log.w(TAG, e);
|
Log.w(TAG, e);
|
||||||
database.markAsSentFailed(messageId);
|
database.markAsSentFailed(messageId);
|
||||||
notifyMediaMessageDeliveryFailed(context, messageId);
|
notifyMediaMessageDeliveryFailed(context, messageId);
|
||||||
@ -94,16 +95,6 @@ public class MmsSendJob extends SendJob {
|
|||||||
notifyMediaMessageDeliveryFailed(context, messageId);
|
notifyMediaMessageDeliveryFailed(context, messageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private OutgoingMmsConnection getMmsConnection(Context context)
|
|
||||||
throws ApnUnavailableException
|
|
||||||
{
|
|
||||||
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
|
|
||||||
return new OutgoingLollipopMmsConnection(context);
|
|
||||||
} else {
|
|
||||||
return new OutgoingLegacyMmsConnection(context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] getPduBytes(MasterSecret masterSecret, SendReq message)
|
private byte[] getPduBytes(MasterSecret masterSecret, SendReq message)
|
||||||
throws IOException, UndeliverableMessageException, InsecureFallbackApprovalException
|
throws IOException, UndeliverableMessageException, InsecureFallbackApprovalException
|
||||||
{
|
{
|
||||||
|
66
src/org/thoughtcrime/securesms/mms/CompatMmsConnection.java
Normal file
66
src/org/thoughtcrime/securesms/mms/CompatMmsConnection.java
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package org.thoughtcrime.securesms.mms;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
|
import android.net.NetworkInfo;
|
||||||
|
import android.os.Build.VERSION;
|
||||||
|
import android.os.Build.VERSION_CODES;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.Inet6Address;
|
||||||
|
import java.net.InterfaceAddress;
|
||||||
|
import java.net.NetworkInterface;
|
||||||
|
import java.net.SocketException;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
|
||||||
|
import ws.com.google.android.mms.MmsException;
|
||||||
|
import ws.com.google.android.mms.pdu.RetrieveConf;
|
||||||
|
import ws.com.google.android.mms.pdu.SendConf;
|
||||||
|
|
||||||
|
public class CompatMmsConnection implements OutgoingMmsConnection, IncomingMmsConnection {
|
||||||
|
private static final String TAG = CompatMmsConnection.class.getSimpleName();
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
|
||||||
|
public CompatMmsConnection(Context context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable @Override public SendConf send(@NonNull byte[] pduBytes)
|
||||||
|
throws UndeliverableMessageException
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Log.w(TAG, "Sending via legacy connection");
|
||||||
|
return new OutgoingLegacyMmsConnection(context).send(pduBytes);
|
||||||
|
} catch (UndeliverableMessageException | ApnUnavailableException e) {
|
||||||
|
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
|
||||||
|
Log.w(TAG, "Falling back to try sending via Lollipop API");
|
||||||
|
return new OutgoingLollipopMmsConnection(context).send(pduBytes);
|
||||||
|
} else {
|
||||||
|
throw new UndeliverableMessageException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable @Override public RetrieveConf retrieve(@NonNull String contentLocation,
|
||||||
|
byte[] transactionId)
|
||||||
|
throws MmsException, MmsRadioException, ApnUnavailableException, IOException
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Log.w(TAG, "Receiving via legacy connection");
|
||||||
|
return new IncomingLegacyMmsConnection(context).retrieve(contentLocation, transactionId);
|
||||||
|
} catch (MmsRadioException | IOException | ApnUnavailableException e) {
|
||||||
|
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
|
||||||
|
Log.w(TAG, "Falling back to try receiving via Lollipop API");
|
||||||
|
return new IncomingLollipopMmsConnection(context).retrieve(contentLocation, transactionId);
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -104,13 +104,9 @@ public class IncomingLegacyMmsConnection extends LegacyMmsConnection implements
|
|||||||
final String targetHost = useProxy
|
final String targetHost = useProxy
|
||||||
? contentApn.getProxy()
|
? contentApn.getProxy()
|
||||||
: Uri.parse(contentApn.getMmsc()).getHost();
|
: Uri.parse(contentApn.getMmsc()).getHost();
|
||||||
try {
|
if (checkRouteToHost(context, targetHost, usingMmsRadio)) {
|
||||||
if (checkRouteToHost(context, targetHost, usingMmsRadio)) {
|
Log.w(TAG, "got successful route to host " + targetHost);
|
||||||
Log.w(TAG, "got successful route to host " + targetHost);
|
pdu = execute(constructRequest(contentApn, useProxy));
|
||||||
pdu = execute(constructRequest(contentApn, useProxy));
|
|
||||||
}
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
Log.w(TAG, ioe);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pdu == null) {
|
if (pdu == null) {
|
||||||
|
@ -18,6 +18,7 @@ package org.thoughtcrime.securesms.mms;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
|
import android.net.NetworkInfo;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -47,6 +48,8 @@ import java.io.BufferedInputStream;
|
|||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@ -57,7 +60,7 @@ public abstract class LegacyMmsConnection {
|
|||||||
|
|
||||||
public static final String USER_AGENT = "Android-Mms/2.0";
|
public static final String USER_AGENT = "Android-Mms/2.0";
|
||||||
|
|
||||||
private static final String TAG = "MmsCommunication";
|
private static final String TAG = LegacyMmsConnection.class.getSimpleName();
|
||||||
|
|
||||||
protected final Context context;
|
protected final Context context;
|
||||||
protected final Apn apn;
|
protected final Apn apn;
|
||||||
@ -88,6 +91,7 @@ public abstract class LegacyMmsConnection {
|
|||||||
return ((TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE)).getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA;
|
return ((TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE)).getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("TryWithIdenticalCatches")
|
||||||
protected static boolean checkRouteToHost(Context context, String host, boolean usingMmsRadio)
|
protected static boolean checkRouteToHost(Context context, String host, boolean usingMmsRadio)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
@ -105,16 +109,29 @@ public abstract class LegacyMmsConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
byte[] ipAddressBytes = inetAddress.getAddress();
|
byte[] ipAddressBytes = inetAddress.getAddress();
|
||||||
if (ipAddressBytes == null || ipAddressBytes.length != 4) {
|
if (ipAddressBytes == null) {
|
||||||
Log.w(TAG, "returning vacuous success since android.net package doesn't support IPv6");
|
Log.w(TAG, "resolved IP address bytes are null, returning true to attempt a connection anyway.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.w(TAG, "Checking route to address: " + host + ", " + inetAddress.getHostAddress());
|
Log.w(TAG, "Checking route to address: " + host + ", " + inetAddress.getHostAddress());
|
||||||
ConnectivityManager manager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
ConnectivityManager manager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
int ipAddress = Conversions.byteArrayToIntLittleEndian(ipAddressBytes, 0);
|
try {
|
||||||
boolean routeToHostObtained = manager.requestRouteToHost(MmsRadio.TYPE_MOBILE_MMS, ipAddress);
|
final Method requestRouteMethod = manager.getClass().getMethod("requestRouteToHostAddress", Integer.TYPE, InetAddress.class);
|
||||||
Log.w(TAG, "requestRouteToHost result: " + routeToHostObtained);
|
final boolean routeToHostObtained = (Boolean) requestRouteMethod.invoke(manager, MmsRadio.TYPE_MOBILE_MMS, inetAddress);
|
||||||
|
Log.w(TAG, "requestRouteToHostAddress(" + inetAddress + ") -> " + routeToHostObtained);
|
||||||
|
return routeToHostObtained;
|
||||||
|
} catch (NoSuchMethodException nsme) {
|
||||||
|
Log.w(TAG, nsme);
|
||||||
|
} catch (IllegalAccessException iae) {
|
||||||
|
Log.w(TAG, iae);
|
||||||
|
} catch (InvocationTargetException ite) {
|
||||||
|
Log.w(TAG, ite);
|
||||||
|
}
|
||||||
|
|
||||||
|
final int ipAddress = Conversions.byteArrayToIntLittleEndian(ipAddressBytes, 0);
|
||||||
|
final boolean routeToHostObtained = manager.requestRouteToHost(MmsRadio.TYPE_MOBILE_MMS, ipAddress);
|
||||||
|
Log.w(TAG, "requestRouteToHost(" + ipAddress + ") -> " + routeToHostObtained);
|
||||||
return routeToHostObtained;
|
return routeToHostObtained;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,8 +205,6 @@ public abstract class LegacyMmsConnection {
|
|||||||
add(new BasicHeader("X-MDN", number));
|
add(new BasicHeader("X-MDN", number));
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Apn {
|
public static class Apn {
|
||||||
|
@ -67,7 +67,7 @@ public abstract class LollipopMmsConnection extends BroadcastReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void waitForResult() throws TimeoutException {
|
protected void waitForResult() throws TimeoutException {
|
||||||
long timeoutExpiration = System.currentTimeMillis() + 30000;
|
long timeoutExpiration = System.currentTimeMillis() + 60000;
|
||||||
while (!resultAvailable) {
|
while (!resultAvailable) {
|
||||||
Util.wait(this, Math.max(1, timeoutExpiration - System.currentTimeMillis()));
|
Util.wait(this, Math.max(1, timeoutExpiration - System.currentTimeMillis()));
|
||||||
if (System.currentTimeMillis() >= timeoutExpiration) {
|
if (System.currentTimeMillis() >= timeoutExpiration) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user