1 /* 2 * Copyright (C) 2007-2008 Esmertec AG. 3 * Copyright (C) 2007-2008 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package com.android.mms.transaction; 19 20 import java.io.IOException; 21 import java.net.InetAddress; 22 import java.net.UnknownHostException; 23 24 import android.content.Context; 25 import android.net.ConnectivityManager; 26 import android.net.Uri; 27 28 import com.android.mms.util.SendingProgressTokenManager; 29 import com.google.android.mms.MmsException; 30 31 /** 32 * Transaction is an abstract class for notification transaction, send transaction 33 * and other transactions described in MMS spec. 34 * It provides the interfaces of them and some common methods for them. 35 */ 36 public abstract class Transaction extends Observable { 37 private final int mServiceId; 38 39 protected Context mContext; 40 protected String mId; 41 protected TransactionState mTransactionState; 42 protected TransactionSettings mTransactionSettings; 43 44 /** 45 * Identifies push requests. 46 */ 47 public static final int NOTIFICATION_TRANSACTION = 0; 48 /** 49 * Identifies deferred retrieve requests. 50 */ 51 public static final int RETRIEVE_TRANSACTION = 1; 52 /** 53 * Identifies send multimedia message requests. 54 */ 55 public static final int SEND_TRANSACTION = 2; 56 /** 57 * Identifies send read report requests. 58 */ 59 public static final int READREC_TRANSACTION = 3; 60 Transaction(Context context, int serviceId, TransactionSettings settings)61 public Transaction(Context context, int serviceId, 62 TransactionSettings settings) { 63 mContext = context; 64 mTransactionState = new TransactionState(); 65 mServiceId = serviceId; 66 mTransactionSettings = settings; 67 } 68 69 /** 70 * Returns the transaction state of this transaction. 71 * 72 * @return Current state of the Transaction. 73 */ 74 @Override getState()75 public TransactionState getState() { 76 return mTransactionState; 77 } 78 79 /** 80 * An instance of Transaction encapsulates the actions required 81 * during a MMS Client transaction. 82 */ process()83 public abstract void process(); 84 85 /** 86 * Used to determine whether a transaction is equivalent to this instance. 87 * 88 * @param transaction the transaction which is compared to this instance. 89 * @return true if transaction is equivalent to this instance, false otherwise. 90 */ isEquivalent(Transaction transaction)91 public boolean isEquivalent(Transaction transaction) { 92 return mId.equals(transaction.mId); 93 } 94 95 /** 96 * Get the service-id of this transaction which was assigned by the framework. 97 * @return the service-id of the transaction 98 */ getServiceId()99 public int getServiceId() { 100 return mServiceId; 101 } 102 getConnectionSettings()103 public TransactionSettings getConnectionSettings() { 104 return mTransactionSettings; 105 } setConnectionSettings(TransactionSettings settings)106 public void setConnectionSettings(TransactionSettings settings) { 107 mTransactionSettings = settings; 108 } 109 110 /** 111 * A common method to send a PDU to MMSC. 112 * 113 * @param pdu A byte array which contains the data of the PDU. 114 * @return A byte array which contains the response data. 115 * If an HTTP error code is returned, an IOException will be thrown. 116 * @throws IOException if any error occurred on network interface or 117 * an HTTP error code(>=400) returned from the server. 118 * @throws MmsException if pdu is null. 119 */ sendPdu(byte[] pdu)120 protected byte[] sendPdu(byte[] pdu) throws IOException, MmsException { 121 return sendPdu(SendingProgressTokenManager.NO_TOKEN, pdu, 122 mTransactionSettings.getMmscUrl()); 123 } 124 125 /** 126 * A common method to send a PDU to MMSC. 127 * 128 * @param pdu A byte array which contains the data of the PDU. 129 * @param mmscUrl Url of the recipient MMSC. 130 * @return A byte array which contains the response data. 131 * If an HTTP error code is returned, an IOException will be thrown. 132 * @throws IOException if any error occurred on network interface or 133 * an HTTP error code(>=400) returned from the server. 134 * @throws MmsException if pdu is null. 135 */ sendPdu(byte[] pdu, String mmscUrl)136 protected byte[] sendPdu(byte[] pdu, String mmscUrl) throws IOException, MmsException { 137 return sendPdu(SendingProgressTokenManager.NO_TOKEN, pdu, mmscUrl); 138 } 139 140 /** 141 * A common method to send a PDU to MMSC. 142 * 143 * @param token The token to identify the sending progress. 144 * @param pdu A byte array which contains the data of the PDU. 145 * @return A byte array which contains the response data. 146 * If an HTTP error code is returned, an IOException will be thrown. 147 * @throws IOException if any error occurred on network interface or 148 * an HTTP error code(>=400) returned from the server. 149 * @throws MmsException if pdu is null. 150 */ sendPdu(long token, byte[] pdu)151 protected byte[] sendPdu(long token, byte[] pdu) throws IOException, MmsException { 152 return sendPdu(token, pdu, mTransactionSettings.getMmscUrl()); 153 } 154 155 /** 156 * A common method to send a PDU to MMSC. 157 * 158 * @param token The token to identify the sending progress. 159 * @param pdu A byte array which contains the data of the PDU. 160 * @param mmscUrl Url of the recipient MMSC. 161 * @return A byte array which contains the response data. 162 * If an HTTP error code is returned, an IOException will be thrown. 163 * @throws IOException if any error occurred on network interface or 164 * an HTTP error code(>=400) returned from the server. 165 * @throws MmsException if pdu is null. 166 */ sendPdu(long token, byte[] pdu, String mmscUrl)167 protected byte[] sendPdu(long token, byte[] pdu, 168 String mmscUrl) throws IOException, MmsException { 169 if (pdu == null) { 170 throw new MmsException(); 171 } 172 173 ensureRouteToHost(mmscUrl, mTransactionSettings); 174 return HttpUtils.httpConnection( 175 mContext, token, 176 mmscUrl, 177 pdu, HttpUtils.HTTP_POST_METHOD, 178 mTransactionSettings.isProxySet(), 179 mTransactionSettings.getProxyAddress(), 180 mTransactionSettings.getProxyPort()); 181 } 182 183 /** 184 * A common method to retrieve a PDU from MMSC. 185 * 186 * @param url The URL of the message which we are going to retrieve. 187 * @return A byte array which contains the data of the PDU. 188 * If the status code is not correct, an IOException will be thrown. 189 * @throws IOException if any error occurred on network interface or 190 * an HTTP error code(>=400) returned from the server. 191 */ getPdu(String url)192 protected byte[] getPdu(String url) throws IOException { 193 ensureRouteToHost(url, mTransactionSettings); 194 return HttpUtils.httpConnection( 195 mContext, SendingProgressTokenManager.NO_TOKEN, 196 url, null, HttpUtils.HTTP_GET_METHOD, 197 mTransactionSettings.isProxySet(), 198 mTransactionSettings.getProxyAddress(), 199 mTransactionSettings.getProxyPort()); 200 } 201 202 /** 203 * Make sure that a network route exists to allow us to reach the host in the 204 * supplied URL, and to the MMS proxy host as well, if a proxy is used. 205 * @param url The URL of the MMSC to which we need a route 206 * @param settings Specifies the address of the proxy host, if any 207 * @throws IOException if the host doesn't exist, or adding the route fails. 208 */ ensureRouteToHost(String url, TransactionSettings settings)209 private void ensureRouteToHost(String url, TransactionSettings settings) throws IOException { 210 ConnectivityManager connMgr = 211 (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 212 213 InetAddress inetAddr; 214 if (settings.isProxySet()) { 215 String proxyAddr = settings.getProxyAddress(); 216 try { 217 inetAddr = InetAddress.getByName(proxyAddr); 218 } catch (UnknownHostException e) { 219 throw new IOException("Cannot establish route for " + url + 220 ": Unknown proxy " + proxyAddr); 221 } 222 if (!connMgr.requestRouteToHostAddress(ConnectivityManager.TYPE_MOBILE_MMS, inetAddr)) { 223 throw new IOException("Cannot establish route to proxy " + inetAddr); 224 } 225 } else { 226 Uri uri = Uri.parse(url); 227 try { 228 inetAddr = InetAddress.getByName(uri.getHost()); 229 } catch (UnknownHostException e) { 230 throw new IOException("Cannot establish route for " + url + ": Unknown host"); 231 } 232 if (!connMgr.requestRouteToHostAddress(ConnectivityManager.TYPE_MOBILE_MMS, inetAddr)) { 233 throw new IOException("Cannot establish route to " + inetAddr + " for " + url); 234 } 235 } 236 } 237 238 @Override toString()239 public String toString() { 240 return getClass().getName() + ": serviceId=" + mServiceId; 241 } 242 243 /** 244 * Get the type of the transaction. 245 * 246 * @return Transaction type in integer. 247 */ getType()248 abstract public int getType(); 249 } 250