mirror of
https://github.com/oxen-io/session-android.git
synced 2025-05-19 16:58:37 +00:00
use URLConnection for MMS because it's better
// FREEBIE
This commit is contained in:
parent
d2edda837a
commit
28e14f47cf
@ -20,28 +20,27 @@ import android.content.Context;
|
|||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.sqlite.SQLiteException;
|
import android.database.sqlite.SQLiteException;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.Uri;
|
|
||||||
import android.net.http.AndroidHttpClient;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.apache.http.HttpEntity;
|
|
||||||
import org.apache.http.HttpHost;
|
|
||||||
import org.apache.http.conn.params.ConnRouteParams;
|
|
||||||
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.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.whispersystems.textsecure.util.Conversions;
|
import org.whispersystems.textsecure.util.Conversions;
|
||||||
import org.whispersystems.textsecure.util.Util;
|
import org.whispersystems.textsecure.util.Util;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.Proxy;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class MmsCommunication {
|
public class MmsCommunication {
|
||||||
|
private static final String TAG = "MmsCommunication";
|
||||||
|
|
||||||
protected static MmsConnectionParameters getLocallyConfiguredMmsConnectionParameters(Context context)
|
protected static MmsConnectionParameters getLocallyConfiguredMmsConnectionParameters(Context context)
|
||||||
throws ApnUnavailableException
|
throws ApnUnavailableException
|
||||||
@ -83,30 +82,40 @@ public class MmsCommunication {
|
|||||||
protected static MmsConnectionParameters getMmsConnectionParameters(Context context, String apn)
|
protected static MmsConnectionParameters getMmsConnectionParameters(Context context, String apn)
|
||||||
throws ApnUnavailableException
|
throws ApnUnavailableException
|
||||||
{
|
{
|
||||||
|
Log.w(TAG, "Getting MMSC params for apn " + apn);
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cursor = DatabaseFactory.getMmsDatabase(context).getCarrierMmsInformation(apn);
|
cursor = DatabaseFactory.getMmsDatabase(context).getCarrierMmsInformation(apn);
|
||||||
|
|
||||||
if (cursor == null || !cursor.moveToFirst())
|
if (cursor == null || !cursor.moveToFirst()) {
|
||||||
return getLocalMmsConnectionParameters(context);
|
MmsConnectionParameters parameters = getLocalMmsConnectionParameters(context);
|
||||||
|
Log.w(TAG, "Android didn't have a result, using MMSC parameters: " + parameters.get().get(0).getMmsc() + " // " + parameters.get().get(0).getProxy() + " // " + parameters.get().get(0).getPort());
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
String mmsc = cursor.getString(cursor.getColumnIndexOrThrow("mmsc"));
|
String mmsc = cursor.getString(cursor.getColumnIndexOrThrow("mmsc"));
|
||||||
String proxy = cursor.getString(cursor.getColumnIndexOrThrow("mmsproxy"));
|
String proxy = cursor.getString(cursor.getColumnIndexOrThrow("mmsproxy"));
|
||||||
String port = cursor.getString(cursor.getColumnIndexOrThrow("mmsport"));
|
String port = cursor.getString(cursor.getColumnIndexOrThrow("mmsport"));
|
||||||
|
|
||||||
if (!Util.isEmpty(mmsc))
|
if (!Util.isEmpty(mmsc)) {
|
||||||
|
Log.w(TAG, "Using Android-provided MMSC parameters: " + mmsc + " // " + proxy + " // " + port);
|
||||||
return new MmsConnectionParameters(mmsc, proxy, port);
|
return new MmsConnectionParameters(mmsc, proxy, port);
|
||||||
|
}
|
||||||
|
|
||||||
} while (cursor.moveToNext());
|
} while (cursor.moveToNext());
|
||||||
|
|
||||||
|
MmsConnectionParameters parameters = getLocalMmsConnectionParameters(context);
|
||||||
|
Log.w(TAG, "Android didn't have a result, using MMSC parameters: " + parameters.get().get(0).getMmsc() + " // " + parameters.get().get(0).getProxy() + " // " + parameters.get().get(0).getPort());
|
||||||
|
return parameters;
|
||||||
} catch (SQLiteException sqe) {
|
} catch (SQLiteException sqe) {
|
||||||
Log.w("MmsCommunication", sqe);
|
Log.w(TAG, sqe);
|
||||||
} catch (SecurityException se) {
|
} catch (SecurityException se) {
|
||||||
Log.i("MmsCommunication", "Couldn't write APN settings, expected. msg: " + se.getMessage());
|
Log.w(TAG, "Android won't let us query the APN database.");
|
||||||
|
return getLocalMmsConnectionParameters(context);
|
||||||
} catch (IllegalArgumentException iae) {
|
} catch (IllegalArgumentException iae) {
|
||||||
Log.w("MmsCommunication", iae);
|
Log.w(TAG, iae);
|
||||||
} finally {
|
} finally {
|
||||||
if (cursor != null)
|
if (cursor != null)
|
||||||
cursor.close();
|
cursor.close();
|
||||||
@ -127,7 +136,7 @@ public class MmsCommunication {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.w("MmsCommunication", "Checking route to address: " + host + " , " + inetAddress.getHostAddress());
|
Log.w(TAG, "Checking route to address: " + host + " , " + inetAddress.getHostAddress());
|
||||||
|
|
||||||
byte[] ipAddressBytes = inetAddress.getAddress();
|
byte[] ipAddressBytes = inetAddress.getAddress();
|
||||||
|
|
||||||
@ -140,33 +149,33 @@ public class MmsCommunication {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static AndroidHttpClient constructHttpClient(Context context, String proxy, int port) {
|
protected static byte[] parseResponse(InputStream is) throws IOException {
|
||||||
AndroidHttpClient client = AndroidHttpClient.newInstance("Android-Mms/2.0", context);
|
InputStream in = new BufferedInputStream(is);
|
||||||
HttpParams params = client.getParams();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
HttpProtocolParams.setContentCharset(params, "UTF-8");
|
Util.copy(in, baos);
|
||||||
HttpConnectionParams.setSoTimeout(params, 20 * 1000);
|
Log.w(TAG, "received full server response, " + baos.size() + " bytes");
|
||||||
|
return baos.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static HttpURLConnection constructHttpClient(String urlString, String proxy, int port)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
HttpURLConnection urlConnection;
|
||||||
|
URL url = new URL(urlString);
|
||||||
if (proxy != null) {
|
if (proxy != null) {
|
||||||
ConnRouteParams.setDefaultProxy(params, new HttpHost(proxy, port));
|
Log.w(TAG, "constructing http client using a proxy");
|
||||||
|
Proxy proxyRoute = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxy, port));
|
||||||
|
urlConnection = (HttpURLConnection) url.openConnection(proxyRoute);
|
||||||
|
} else {
|
||||||
|
Log.w(TAG, "constructing http client without proxy");
|
||||||
|
urlConnection = (HttpURLConnection) url.openConnection();
|
||||||
}
|
}
|
||||||
|
urlConnection.setConnectTimeout(20*1000);
|
||||||
return client;
|
urlConnection.setReadTimeout(20*1000);
|
||||||
}
|
urlConnection.setUseCaches(false);
|
||||||
|
urlConnection.setRequestProperty("User-Agent", "Android-Mms/2.0");
|
||||||
protected static byte[] parseResponse(HttpEntity entity) throws IOException {
|
urlConnection.setRequestProperty("Accept-Charset", "UTF-8");
|
||||||
if (entity == null || entity.getContentLength() == 0)
|
return urlConnection;
|
||||||
return null;
|
|
||||||
|
|
||||||
if (entity.getContentLength() < 0)
|
|
||||||
throw new IOException("Unknown content length!");
|
|
||||||
|
|
||||||
byte[] responseBytes = new byte[(int)entity.getContentLength()];
|
|
||||||
DataInputStream dataInputStream = new DataInputStream(entity.getContent());
|
|
||||||
dataInputStream.readFully(responseBytes);
|
|
||||||
dataInputStream.close();
|
|
||||||
|
|
||||||
entity.consumeContent();
|
|
||||||
return responseBytes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static class MmsConnectionParameters {
|
protected static class MmsConnectionParameters {
|
||||||
|
@ -18,50 +18,49 @@ package org.thoughtcrime.securesms.mms;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.net.http.AndroidHttpClient;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.apache.http.HttpHost;
|
|
||||||
import org.apache.http.HttpResponse;
|
|
||||||
import org.apache.http.StatusLine;
|
|
||||||
import org.apache.http.client.methods.HttpGet;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.io.InputStream;
|
||||||
import java.net.URISyntaxException;
|
import java.net.HttpURLConnection;
|
||||||
|
|
||||||
import ws.com.google.android.mms.pdu.PduParser;
|
import ws.com.google.android.mms.pdu.PduParser;
|
||||||
import ws.com.google.android.mms.pdu.RetrieveConf;
|
import ws.com.google.android.mms.pdu.RetrieveConf;
|
||||||
|
|
||||||
public class MmsDownloadHelper extends MmsCommunication {
|
public class MmsDownloadHelper extends MmsCommunication {
|
||||||
|
private static final String TAG = MmsDownloadHelper.class.getSimpleName();
|
||||||
|
|
||||||
private static byte[] makeRequest(Context context, String url, String proxy, int proxyPort)
|
private static byte[] makeRequest(String url, String proxy, int proxyPort)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
AndroidHttpClient client = null;
|
HttpURLConnection client = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
client = constructHttpClient(context, proxy, proxyPort);
|
client = constructHttpClient(url, 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());
|
|
||||||
|
|
||||||
request.setParams(client.getParams());
|
client.setDoInput(true);
|
||||||
request.addHeader("Accept", "*/*, application/vnd.wap.mms-message, application/vnd.wap.sic");
|
client.setRequestMethod("GET");
|
||||||
|
client.setRequestProperty("Accept", "*/*, application/vnd.wap.mms-message, application/vnd.wap.sic");
|
||||||
|
|
||||||
HttpResponse response = client.execute(target, request);
|
Log.w(TAG, "connecting to " + url);
|
||||||
StatusLine status = response.getStatusLine();
|
client.connect();
|
||||||
|
|
||||||
if (status.getStatusCode() != 200)
|
final InputStream is;
|
||||||
throw new IOException("Non-successful HTTP response: " + status.getReasonPhrase());
|
try {
|
||||||
|
is = client.getInputStream();
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
Log.w(TAG, "failed with response code " + client.getResponseCode() + " / " + client.getResponseMessage());
|
||||||
|
throw ioe;
|
||||||
|
}
|
||||||
|
|
||||||
return parseResponse(response.getEntity());
|
Log.w(TAG, "response code was " + client.getResponseCode() + "/" + client.getResponseMessage());
|
||||||
} catch (URISyntaxException use) {
|
if (client.getResponseCode() != 200) {
|
||||||
Log.w("MmsDownloadHelper", use);
|
throw new IOException("non-200 response");
|
||||||
throw new IOException("Couldn't parse URI");
|
}
|
||||||
|
|
||||||
|
return parseResponse(is);
|
||||||
} finally {
|
} finally {
|
||||||
if (client != null)
|
if (client != null) client.disconnect();
|
||||||
client.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,11 +84,11 @@ public class MmsDownloadHelper extends MmsCommunication {
|
|||||||
try {
|
try {
|
||||||
if (proxyIfPossible && param.hasProxy()) {
|
if (proxyIfPossible && param.hasProxy()) {
|
||||||
if (checkRouteToHost(context, param.getProxy(), usingMmsRadio)) {
|
if (checkRouteToHost(context, param.getProxy(), usingMmsRadio)) {
|
||||||
pdu = makeRequest(context, url, param.getProxy(), param.getPort());
|
pdu = makeRequest(url, param.getProxy(), param.getPort());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (checkRouteToHost(context, Uri.parse(url).getHost(), usingMmsRadio)) {
|
if (checkRouteToHost(context, Uri.parse(url).getHost(), usingMmsRadio)) {
|
||||||
pdu = makeRequest(context, url, null, -1);
|
pdu = makeRequest(url, null, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,17 +20,15 @@ import android.content.Context;
|
|||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.NetworkInfo;
|
import android.net.NetworkInfo;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.net.http.AndroidHttpClient;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.apache.http.HttpHost;
|
|
||||||
import org.apache.http.HttpResponse;
|
|
||||||
import org.apache.http.StatusLine;
|
|
||||||
import org.apache.http.client.methods.HttpPost;
|
|
||||||
import org.apache.http.entity.ByteArrayEntity;
|
|
||||||
import org.whispersystems.textsecure.util.Util;
|
import org.whispersystems.textsecure.util.Util;
|
||||||
|
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
@ -40,42 +38,53 @@ import ws.com.google.android.mms.pdu.SendConf;
|
|||||||
public class MmsSendHelper extends MmsCommunication {
|
public class MmsSendHelper extends MmsCommunication {
|
||||||
private final static String TAG = MmsSendHelper.class.getSimpleName();
|
private final static String TAG = MmsSendHelper.class.getSimpleName();
|
||||||
|
|
||||||
private static byte[] makePost(Context context, String url, String proxy, int proxyPort, byte[] mms)
|
private static byte[] makePost(String url, String proxy, int proxyPort, byte[] mms)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
AndroidHttpClient client = null;
|
if (mms == null) return null;
|
||||||
|
|
||||||
|
HttpURLConnection client = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Log.w(TAG, "Sending MMS1 of length: " + (mms != null ? mms.length : "null"));
|
client = constructHttpClient(url, proxy, proxyPort);
|
||||||
client = constructHttpClient(context, proxy, proxyPort);
|
client.setFixedLengthStreamingMode(mms.length);
|
||||||
|
client.setDoInput(true);
|
||||||
|
client.setDoOutput(true);
|
||||||
|
client.setRequestMethod("POST");
|
||||||
URI targetUrl = new URI(url);
|
URI targetUrl = new URI(url);
|
||||||
|
|
||||||
if (Util.isEmpty(targetUrl.getHost()))
|
if (Util.isEmpty(targetUrl.getHost()))
|
||||||
throw new IOException("Invalid target host: " + targetUrl.getHost() + " , " + targetUrl);
|
throw new IOException("Invalid target host: " + targetUrl.getHost() + " , " + targetUrl);
|
||||||
|
|
||||||
HttpHost target = new HttpHost(targetUrl.getHost(), targetUrl.getPort(), HttpHost.DEFAULT_SCHEME_NAME);
|
client.setRequestProperty("Content-Type", "application/vnd.wap.mms-message");
|
||||||
HttpPost request = new HttpPost(url);
|
client.setRequestProperty("Accept", "*/*, application/vnd.wap.mms-message, application/vnd.wap.sic");
|
||||||
ByteArrayEntity entity = new ByteArrayEntity(mms);
|
client.setRequestProperty("x-wap-profile", "http://www.google.com/oha/rdf/ua-profile-kila.xml");
|
||||||
|
|
||||||
entity.setContentType("application/vnd.wap.mms-message");
|
Log.w(TAG, "connecting to " + targetUrl);
|
||||||
|
client.connect();
|
||||||
request.setEntity(entity);
|
Log.w(TAG, "writing mms payload, " + mms.length + " bytes");
|
||||||
request.setParams(client.getParams());
|
OutputStream out = new BufferedOutputStream(client.getOutputStream());
|
||||||
request.addHeader("Accept", "*/*, application/vnd.wap.mms-message, application/vnd.wap.sic");
|
out.write(mms);
|
||||||
request.addHeader("x-wap-profile", "http://www.google.com/oha/rdf/ua-profile-kila.xml");
|
out.flush();
|
||||||
HttpResponse response = client.execute(target, request);
|
out.close();
|
||||||
StatusLine status = response.getStatusLine();
|
Log.w(TAG, "payload sent");
|
||||||
|
final InputStream is;
|
||||||
if (status.getStatusCode() != 200)
|
try {
|
||||||
throw new IOException("Non-successful HTTP response: " + status.getReasonPhrase());
|
is = client.getInputStream();
|
||||||
|
} catch (IOException ioe) {
|
||||||
return parseResponse(response.getEntity());
|
Log.w(TAG, "failed with response code " + client.getResponseCode() + " / " + client.getResponseMessage());
|
||||||
|
throw ioe;
|
||||||
|
}
|
||||||
|
Log.w(TAG, "response code was " + client.getResponseCode() + "/" + client.getResponseMessage());
|
||||||
|
if (client.getResponseCode() != 200) {
|
||||||
|
throw new IOException("non-200 response");
|
||||||
|
}
|
||||||
|
return parseResponse(is);
|
||||||
} catch (URISyntaxException use) {
|
} catch (URISyntaxException use) {
|
||||||
Log.w(TAG, use);
|
Log.w(TAG, use);
|
||||||
throw new IOException("Couldn't parse URI.");
|
throw new IOException("Couldn't parse URI.");
|
||||||
} finally {
|
} finally {
|
||||||
if (client != null)
|
if (client != null) client.disconnect();
|
||||||
client.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +107,7 @@ public class MmsSendHelper extends MmsCommunication {
|
|||||||
boolean usingMmsRadio, boolean useProxyIfAvailable)
|
boolean usingMmsRadio, boolean useProxyIfAvailable)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
Log.w(TAG, "Sending MMS of length: " + mms.length);
|
Log.w(TAG, "Sending MMS of length: " + mms.length + "." + (usingMmsRadio ? " using mms radio" : ""));
|
||||||
try {
|
try {
|
||||||
MmsConnectionParameters parameters = getMmsConnectionParameters(context, apn);
|
MmsConnectionParameters parameters = getMmsConnectionParameters(context, apn);
|
||||||
|
|
||||||
@ -106,12 +115,12 @@ public class MmsSendHelper extends MmsCommunication {
|
|||||||
try {
|
try {
|
||||||
if (useProxyIfAvailable && param.hasProxy()) {
|
if (useProxyIfAvailable && param.hasProxy()) {
|
||||||
if (checkRouteToHost(context, param.getProxy(), usingMmsRadio)) {
|
if (checkRouteToHost(context, param.getProxy(), usingMmsRadio)) {
|
||||||
byte[] response = makePost(context, param.getMmsc(), param.getProxy(), param.getPort(), mms);
|
byte[] response = makePost(param.getMmsc(), param.getProxy(), param.getPort(), mms);
|
||||||
if (response != null) return response;
|
if (response != null) return response;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (checkRouteToHost(context, Uri.parse(param.getMmsc()).getHost(), usingMmsRadio)) {
|
if (checkRouteToHost(context, Uri.parse(param.getMmsc()).getHost(), usingMmsRadio)) {
|
||||||
byte[] response = makePost(context, param.getMmsc(), null, -1, mms);
|
byte[] response = makePost(param.getMmsc(), null, -1, mms);
|
||||||
if (response != null) return response;
|
if (response != null) return response;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user