Change MMS network request pattern.

Currently we're flipping the radio in "MMS" mode, and connecting through
any proxies specified in the APN.  This always work, or at least doesn't
seem to work on Sprint, since the configured mms proxy rejects proxy
requests.

Instead we try the following in this order:

1) Connect over normal data connection directly to MMSC.
2) Connect over MMS radio connection to MMSC.
3) Connect over MMS radio connection with any configured proxy to MMSC.

Hopefully this doesn't fuck up shit on other unknown networks.
This commit is contained in:
Moxie Marlinspike
2013-02-20 18:10:33 -08:00
parent df05508a6f
commit f73adfc8f5
6 changed files with 315 additions and 174 deletions

View File

@@ -63,7 +63,8 @@ public class MmsCommunication {
throw new ApnUnavailableException("No locally configured parameters available");
}
protected static MmsConnectionParameters getMmsConnectionParameters(Context context, String apn)
protected static MmsConnectionParameters getMmsConnectionParameters(Context context, String apn,
boolean proxyIfPossible)
throws ApnUnavailableException
{
Cursor cursor = null;
@@ -76,8 +77,13 @@ public class MmsCommunication {
do {
String mmsc = cursor.getString(cursor.getColumnIndexOrThrow("mmsc"));
String proxy = cursor.getString(cursor.getColumnIndexOrThrow("mmsproxy"));
String port = cursor.getString(cursor.getColumnIndexOrThrow("mmsport"));
String proxy = null;
String port = null;
if (proxyIfPossible) {
proxy = cursor.getString(cursor.getColumnIndexOrThrow("mmsproxy"));
port = cursor.getString(cursor.getColumnIndexOrThrow("mmsport"));
}
if (mmsc != null && !mmsc.equals(""))
return new MmsConnectionParameters(mmsc, proxy, port);
@@ -97,15 +103,29 @@ public class MmsCommunication {
}
}
protected static void checkRouteToHost(Context context, MmsConnectionParameters parameters, String url) throws IOException {
protected static void checkRouteToHost(Context context, MmsConnectionParameters parameters,
String url, boolean usingMmsRadio)
throws IOException
{
if (parameters == null || !parameters.hasProxy())
checkRouteToHost(context, Uri.parse(url).getHost());
checkRouteToHost(context, Uri.parse(url).getHost(), usingMmsRadio);
else
checkRouteToHost(context, parameters.getProxy());
checkRouteToHost(context, parameters.getProxy(), usingMmsRadio);
}
private static void checkRouteToHost(Context context, String host) throws IOException {
InetAddress inetAddress = InetAddress.getByName(host);
private static void checkRouteToHost(Context context, String host, boolean usingMmsRadio)
throws IOException
{
InetAddress inetAddress = InetAddress.getByName(host);
if (!usingMmsRadio) {
if (inetAddress.isSiteLocalAddress()) {
throw new IOException("RFC1918 address in non-MMS radio situation!");
}
return;
}
byte[] ipAddressBytes = inetAddress.getAddress();
int ipAddress = Conversions.byteArrayToIntLittleEndian(ipAddressBytes, 0);
ConnectivityManager manager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);

View File

@@ -26,6 +26,9 @@ import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import ws.com.google.android.mms.pdu.PduParser;
import ws.com.google.android.mms.pdu.RetrieveConf;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
@@ -46,15 +49,6 @@ public class MmsDownloadHelper extends MmsCommunication {
request.setParams(client.getParams());
request.addHeader("Accept", "*/*, application/vnd.wap.mms-message, application/vnd.wap.sic");
// java.util.logging.Logger.getLogger("org.apache.http.wire").setLevel(java.util.logging.Level.FINEST);
// java.util.logging.Logger.getLogger("org.apache.http.headers").setLevel(java.util.logging.Level.FINEST);
//
// System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog");
// System.setProperty("org.apache.commons.logging.simplelog.showdatetime", "true");
// System.setProperty("org.apache.commons.logging.simplelog.log.httpclient.wire", "debug");
// System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.http", "debug");
// System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.http.headers", "debug");
HttpResponse response = client.execute(target, request);
StatusLine status = response.getStatusLine();
@@ -71,17 +65,29 @@ public class MmsDownloadHelper extends MmsCommunication {
}
}
public static byte[] retrieveMms(Context context, String url, String apn) throws IOException {
public static RetrieveConf retrieveMms(Context context, String url, String apn,
boolean usingMmsRadio, boolean proxyIfPossible)
throws IOException
{
MmsConnectionParameters connectionParameters;
try {
connectionParameters = getMmsConnectionParameters(context, apn);
connectionParameters = getMmsConnectionParameters(context, apn, proxyIfPossible);
} catch (ApnUnavailableException aue) {
Log.w("MmsDownloadHelper", aue);
connectionParameters = new MmsConnectionParameters(null, null, null);
}
checkRouteToHost(context, connectionParameters, url);
return makeRequest(context, connectionParameters, url);
checkRouteToHost(context, connectionParameters, url, usingMmsRadio);
byte[] pdu = makeRequest(context, connectionParameters, url);
RetrieveConf retrieved = (RetrieveConf)new PduParser(pdu).parse();
if (retrieved == null) {
throw new IOException("Bad retrieved PDU");
}
return retrieved;
}
}

View File

@@ -27,6 +27,9 @@ import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import ws.com.google.android.mms.pdu.PduParser;
import ws.com.google.android.mms.pdu.SendConf;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
@@ -66,12 +69,16 @@ public class MmsSendHelper extends MmsCommunication {
}
}
public static byte[] sendMms(Context context, byte[] mms, String apn) throws IOException {
public static SendConf sendMms(Context context, byte[] mms, String apn,
boolean usingMmsRadio, boolean useProxyIfAvailable)
throws IOException
{
Log.w("MmsSender", "Sending MMS of length: " + mms.length);
try {
MmsConnectionParameters parameters = getMmsConnectionParameters(context, apn);
checkRouteToHost(context, parameters, parameters.getMmsc());
return makePost(context, parameters, mms);
MmsConnectionParameters parameters = getMmsConnectionParameters(context, apn, useProxyIfAvailable);
checkRouteToHost(context, parameters, parameters.getMmsc(), usingMmsRadio);
byte[] response = makePost(context, parameters, mms);
return (SendConf) new PduParser(response).parse();
} catch (ApnUnavailableException aue) {
Log.w("MmsSender", aue);
throw new IOException("Failed to get MMSC information...");