MMS Fixes

1) Respect proxyIfPossible flag and make sure to try all mms APNs

2) Reorder mmsc connection process
This commit is contained in:
rymdhund 2014-07-30 00:31:20 +02:00 committed by Moxie Marlinspike
parent d3da409774
commit feabbb33d2
6 changed files with 72 additions and 55 deletions

View File

@ -86,7 +86,7 @@ public class MmsPreferencesActivity extends PassphraseRequiredSherlockPreference
}
private void initializePreferences() {
if (!MmsDownloadHelper.isMmsConnectionParametersAvailable(this, null, false)) {
if (!MmsDownloadHelper.isMmsConnectionParametersAvailable(this, null)) {
TextSecurePreferences.setUseLocalApnsEnabled(this, true);
addPreferencesFromResource(R.xml.mms_preferences);
this.findPreference(TextSecurePreferences.ENABLE_MANUAL_MMS_PREF).setOnPreferenceChangeListener(new OverrideMmsChangeListener());

View File

@ -31,9 +31,8 @@ import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.service.MmsDownloader;
import org.whispersystems.textsecure.util.Conversions;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.textsecure.util.Conversions;
import org.whispersystems.textsecure.util.Util;
import java.io.DataInputStream;
@ -81,8 +80,7 @@ public class MmsCommunication {
}
}
protected static MmsConnectionParameters getMmsConnectionParameters(Context context, String apn,
boolean proxyIfPossible)
protected static MmsConnectionParameters getMmsConnectionParameters(Context context, String apn)
throws ApnUnavailableException
{
Cursor cursor = null;
@ -95,46 +93,28 @@ public class MmsCommunication {
do {
String mmsc = cursor.getString(cursor.getColumnIndexOrThrow("mmsc"));
String proxy = null;
String port = null;
if (proxyIfPossible) {
proxy = cursor.getString(cursor.getColumnIndexOrThrow("mmsproxy"));
port = cursor.getString(cursor.getColumnIndexOrThrow("mmsport"));
}
String proxy = cursor.getString(cursor.getColumnIndexOrThrow("mmsproxy"));
String port = cursor.getString(cursor.getColumnIndexOrThrow("mmsport"));
if (!Util.isEmpty(mmsc))
return new MmsConnectionParameters(mmsc, proxy, port);
} while (cursor.moveToNext());
return getLocalMmsConnectionParameters(context);
} catch (SQLiteException sqe) {
Log.w("MmsCommunication", sqe);
return getLocalMmsConnectionParameters(context);
} catch (SecurityException se) {
Log.i("MmsCommunication", "Couldn't write APN settings, expected. msg: " + se.getMessage());
return getLocalMmsConnectionParameters(context);
} catch (IllegalArgumentException iae) {
Log.w("MmsCommunication", iae);
return getLocalMmsConnectionParameters(context);
} finally {
if (cursor != null)
cursor.close();
}
return getLocalMmsConnectionParameters(context);
}
protected static boolean checkRouteToHost(Context context, MmsConnectionParameters.Apn parameters,
String url, boolean usingMmsRadio)
throws IOException
{
if (parameters == null || !parameters.hasProxy())
return checkRouteToHost(context, Uri.parse(url).getHost(), usingMmsRadio);
else
return checkRouteToHost(context, parameters.getProxy(), usingMmsRadio);
}
private static boolean checkRouteToHost(Context context, String host, boolean usingMmsRadio)
protected static boolean checkRouteToHost(Context context, String host, boolean usingMmsRadio)
throws IOException
{
InetAddress inetAddress = InetAddress.getByName(host);
@ -160,14 +140,14 @@ public class MmsCommunication {
return true;
}
protected static AndroidHttpClient constructHttpClient(Context context, MmsConnectionParameters.Apn mmsConfig) {
protected static AndroidHttpClient constructHttpClient(Context context, String proxy, int port) {
AndroidHttpClient client = AndroidHttpClient.newInstance("Android-Mms/2.0", context);
HttpParams params = client.getParams();
HttpProtocolParams.setContentCharset(params, "UTF-8");
HttpConnectionParams.setSoTimeout(params, 20 * 1000);
if (mmsConfig.hasProxy()) {
ConnRouteParams.setDefaultProxy(params, new HttpHost(mmsConfig.getProxy(), mmsConfig.getPort()));
if (proxy != null) {
ConnRouteParams.setDefaultProxy(params, new HttpHost(proxy, port));
}
return client;

View File

@ -17,6 +17,7 @@
package org.thoughtcrime.securesms.mms;
import android.content.Context;
import android.net.Uri;
import android.net.http.AndroidHttpClient;
import android.util.Log;
@ -34,13 +35,13 @@ import ws.com.google.android.mms.pdu.RetrieveConf;
public class MmsDownloadHelper extends MmsCommunication {
private static byte[] makeRequest(Context context, MmsConnectionParameters.Apn connectionParameters, String url)
private static byte[] makeRequest(Context context, String url, String proxy, int proxyPort)
throws IOException
{
AndroidHttpClient client = null;
try {
client = constructHttpClient(context, connectionParameters);
client = constructHttpClient(context, proxy, proxyPort);
URI targetUrl = new URI(url.trim());
HttpHost target = new HttpHost(targetUrl.getHost(), targetUrl.getPort(), HttpHost.DEFAULT_SCHEME_NAME);
HttpGet request = new HttpGet(url.trim());
@ -64,9 +65,9 @@ public class MmsDownloadHelper extends MmsCommunication {
}
}
public static boolean isMmsConnectionParametersAvailable(Context context, String apn, boolean proxyIfPossible) {
public static boolean isMmsConnectionParametersAvailable(Context context, String apn) {
try {
getMmsConnectionParameters(context, apn, proxyIfPossible);
getMmsConnectionParameters(context, apn);
return true;
} catch (ApnUnavailableException e) {
return false;
@ -77,12 +78,28 @@ public class MmsDownloadHelper extends MmsCommunication {
boolean usingMmsRadio, boolean proxyIfPossible)
throws IOException, ApnUnavailableException
{
MmsConnectionParameters connectionParameters = getMmsConnectionParameters(context, apn, proxyIfPossible);
MmsConnectionParameters connectionParameters = getMmsConnectionParameters(context, apn);
byte[] pdu = null;
for (MmsConnectionParameters.Apn param : connectionParameters.get()) {
if (checkRouteToHost(context, param, param.getMmsc(), usingMmsRadio)) {
pdu = makeRequest(context, param, url);
String proxy = null;
int proxyPort = 80;
boolean hasRoute;
if (proxyIfPossible && param.hasProxy()) {
proxy = param.getProxy();
proxyPort = param.getPort();
hasRoute = checkRouteToHost(context, proxy, usingMmsRadio);
} else {
hasRoute = checkRouteToHost(context, Uri.parse(param.getMmsc()).getHost(), usingMmsRadio);
}
if (hasRoute) {
try {
pdu = makeRequest(context, url, proxy, proxyPort);
} catch(IOException e) {
Log.w("MmsDownloadHelper", "Request failed: "+e.getMessage());
}
if (pdu != null) break;
}
}

View File

@ -19,6 +19,7 @@ package org.thoughtcrime.securesms.mms;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.http.AndroidHttpClient;
import android.util.Log;
@ -39,21 +40,21 @@ import ws.com.google.android.mms.pdu.SendConf;
public class MmsSendHelper extends MmsCommunication {
private final static String TAG = MmsSendHelper.class.getSimpleName();
private static byte[] makePost(Context context, MmsConnectionParameters.Apn parameters, byte[] mms)
private static byte[] makePost(Context context, String url, String proxy, int proxyPort, byte[] mms)
throws IOException
{
AndroidHttpClient client = null;
try {
Log.w(TAG, "Sending MMS1 of length: " + (mms != null ? mms.length : "null"));
client = constructHttpClient(context, parameters);
URI targetUrl = new URI(parameters.getMmsc());
client = constructHttpClient(context, proxy, proxyPort);
URI targetUrl = new URI(url);
if (Util.isEmpty(targetUrl.getHost()))
throw new IOException("Invalid target host: " + targetUrl.getHost() + " , " + targetUrl);
HttpHost target = new HttpHost(targetUrl.getHost(), targetUrl.getPort(), HttpHost.DEFAULT_SCHEME_NAME);
HttpPost request = new HttpPost(parameters.getMmsc());
HttpPost request = new HttpPost(url);
ByteArrayEntity entity = new ByteArrayEntity(mms);
entity.setContentType("application/vnd.wap.mms-message");
@ -99,11 +100,27 @@ public class MmsSendHelper extends MmsCommunication {
{
Log.w(TAG, "Sending MMS of length: " + mms.length);
try {
MmsConnectionParameters parameters = getMmsConnectionParameters(context, apn, useProxyIfAvailable);
MmsConnectionParameters parameters = getMmsConnectionParameters(context, apn);
for (MmsConnectionParameters.Apn param : parameters.get()) {
if (checkRouteToHost(context, param, param.getMmsc(), usingMmsRadio)) {
byte[] response = makePost(context, param, mms);
if (response != null) return response;
String proxy = null;
int proxyPort = 80;
boolean hasRoute;
if(useProxyIfAvailable && param.hasProxy()){
proxy = param.getProxy();
proxyPort = param.getPort();
hasRoute = checkRouteToHost(context, proxy, usingMmsRadio);
} else {
hasRoute = checkRouteToHost(context, Uri.parse(param.getMmsc()).getHost(), usingMmsRadio);
}
if (hasRoute) {
try {
byte[] response = makePost(context, param.getMmsc(), proxy, proxyPort, mms);
if (response != null) return response;
} catch(IOException e) {
Log.w("MmsSendHelper", "Request failed: "+e.getMessage());
}
}
}
throw new IOException("Connection manager could not obtain route to host.");
@ -123,7 +140,7 @@ public class MmsSendHelper extends MmsCommunication {
}
String apn = networkInfo.getExtraInfo();
MmsCommunication.getMmsConnectionParameters(context, apn, true);
MmsCommunication.getMmsConnectionParameters(context, apn);
return true;
} catch (ApnUnavailableException e) {
Log.w("MmsSendHelper", e);

View File

@ -18,6 +18,7 @@ package org.thoughtcrime.securesms.service;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.util.Pair;
@ -69,7 +70,7 @@ public class MmsDownloader {
}
private void handleMmsPendingApnDownloads(MasterSecret masterSecret) {
if (!MmsDownloadHelper.isMmsConnectionParametersAvailable(context, null, false))
if (!MmsDownloadHelper.isMmsConnectionParametersAvailable(context, null))
return;
MmsDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context);
@ -100,6 +101,8 @@ public class MmsDownloader {
database.markDownloadState(messageId, MmsDatabase.Status.DOWNLOAD_CONNECTING);
Log.w("MmsDownloader", "Downloading mms at "+ Uri.parse(contentLocation).getHost());
try {
if (isCdmaNetwork()) {
Log.w("MmsDownloader", "Connecting directly...");
@ -115,22 +118,22 @@ public class MmsDownloader {
Log.w("MmsDownloader", "Changing radio to MMS mode..");
radio.connect();
Log.w("MmsDownloader", "Downloading in MMS mode without proxy...");
Log.w("MmsDownloader", "Downloading in MMS mode with proxy...");
try {
retrieveAndStore(masterSecret, messageId, threadId, contentLocation,
transactionId, true, false);
transactionId, true, true);
radio.disconnect();
return;
} catch (IOException e) {
Log.w("MmsDownloader", e);
}
Log.w("MmsDownloader", "Downloading in MMS mode with proxy...");
Log.w("MmsDownloader", "Downloading in MMS mode without proxy...");
try {
retrieveAndStore(masterSecret, messageId, threadId,
contentLocation, transactionId, true, true);
contentLocation, transactionId, true, false);
radio.disconnect();
return;
} catch (IOException e) {

View File

@ -80,21 +80,21 @@ public class MmsTransport {
}
}
Log.w("MmsTransport", "Sending MMS with radio change...");
Log.w("MmsTransport", "Sending MMS with radio change and proxy...");
radio.connect();
try {
MmsSendResult result = sendMms(message, true, false);
MmsSendResult result = sendMms(message, true, true);
radio.disconnect();
return result;
} catch (IOException e) {
Log.w("MmsTransport", e);
}
Log.w("MmsTransport", "Sending MMS with radio change and proxy...");
Log.w("MmsTransport", "Sending MMS with radio change and without proxy...");
try {
MmsSendResult result = sendMms(message, true, true);
MmsSendResult result = sendMms(message, true, false);
radio.disconnect();
return result;
} catch (IOException ioe) {