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.im.imps; 19 20 import java.util.Map; 21 22 import com.android.im.engine.ConnectionConfig; 23 import com.android.im.engine.ImException; 24 import com.android.im.imps.ImpsConstants.ImpsVersion; 25 import com.android.im.plugin.ImpsConfigNames; 26 import com.android.im.plugin.PasswordDigest; 27 import com.android.im.plugin.PresenceMapping; 28 29 /** 30 * The configuration for IMPS connection. 31 */ 32 public class ImpsConnectionConfig extends ConnectionConfig { 33 private static final int DEFAULT_KEEPALIVE_SECONDS = 2 * 60 * 60; // 2 hour 34 private static final int DEFAULT_MIN_SERVER_POLL = 30; // seconds 35 36 private static final int DEFAULT_SMS_PORT = 3590; 37 private static final int DEFAULT_SMS_CIR_PORT = 3716; 38 private static final long DEFAULT_PRESENCE_POLL_INTERVAL = 60 * 1000; // 1 minute 39 40 // DeliveryReport is good for acknowledgment but consumes 2 extra 41 // transactions + 1 possible CIR notification per message. Should not 42 // be enabled on limited/slow connections. 43 private static final boolean NEED_DELIVERY_REPORT = false; 44 45 private ImpsVersion mImpsVersion = ImpsVersion.IMPS_VERSION_12; 46 47 private TransportType mDataChannelBinding = TransportType.HTTP; 48 private CirMethod mCirChannelBinding = CirMethod.STCP; 49 private EncodingType mDataEncoding = EncodingType.WBXML; 50 private boolean mSecureLogin = true; // default to use 4-way login 51 private boolean mBasicPresenceOnly = false; 52 private String mHost = ""; 53 private String mClientId = "JiMMY"; 54 private String mMsisdn; 55 56 private int mUdpPort = 3717; 57 private int mReplyTimeout = 45 * 1000; 58 59 private String mContentType; 60 private String mVersionNs; 61 private String mTransactionNs; 62 private String mPresenceNs; 63 64 private PresenceMapping mPresenceMapping; 65 private PasswordDigest mPasswordDigest; 66 67 private String mDefaultDomain; 68 69 private String mCustomPasswordDigest; 70 private String mCustomPresenceMapping; 71 72 private String mPluginPath; 73 74 private Map<String, String> mOthers; 75 ImpsConnectionConfig()76 public ImpsConnectionConfig() { 77 setupVersionStrings(); 78 } 79 ImpsConnectionConfig(Map<String, String> map)80 public ImpsConnectionConfig(Map<String, String> map) { 81 String dataChannel = map.get(ImpsConfigNames.DATA_CHANNEL); 82 try { 83 mDataChannelBinding = TransportType.valueOf(dataChannel); 84 } catch (IllegalArgumentException e) { 85 ImpsLog.log("Unknown DataChannel: " + dataChannel +", using HTTP"); 86 mDataChannelBinding = TransportType.HTTP; 87 } 88 89 String dataEncoding = map.get(ImpsConfigNames.DATA_ENCODING); 90 try { 91 mDataEncoding = EncodingType.valueOf(dataEncoding); 92 } catch (IllegalArgumentException e) { 93 ImpsLog.log("Unknown DataEncoding: " + dataEncoding +", using WBXML"); 94 mDataEncoding = EncodingType.WBXML; 95 } 96 97 String cirChannel = map.get(ImpsConfigNames.CIR_CHANNEL); 98 try { 99 mCirChannelBinding = CirMethod.valueOf(cirChannel); 100 } catch (IllegalArgumentException e) { 101 ImpsLog.log("Unknown CirChannel: " + cirChannel +", using TCP"); 102 mCirChannelBinding = CirMethod.STCP; 103 } 104 105 mHost = map.get(ImpsConfigNames.HOST); 106 107 if (map.get(ImpsConfigNames.CLIENT_ID) != null) { 108 mClientId = map.get(ImpsConfigNames.CLIENT_ID); 109 } 110 111 if (map.get(ImpsConfigNames.MSISDN) != null) { 112 mMsisdn = map.get(ImpsConfigNames.MSISDN); 113 } 114 if (map.get(ImpsConfigNames.SECURE_LOGIN) != null) { 115 mSecureLogin = isTrue(map.get(ImpsConfigNames.SECURE_LOGIN)); 116 } 117 if (map.get(ImpsConfigNames.BASIC_PA_ONLY) != null) { 118 mBasicPresenceOnly = isTrue(map.get(ImpsConfigNames.BASIC_PA_ONLY)); 119 } 120 if (map.containsKey(ImpsConfigNames.VERSION)) { 121 mImpsVersion = ImpsVersion.fromString( 122 map.get(ImpsConfigNames.VERSION)); 123 } 124 setupVersionStrings(); 125 126 mDefaultDomain = map.get(ImpsConfigNames.DEFAULT_DOMAIN); 127 128 mPluginPath = map.get(ImpsConfigNames.PLUGIN_PATH); 129 mCustomPasswordDigest = map.get(ImpsConfigNames.CUSTOM_PASSWORD_DIGEST); 130 mCustomPresenceMapping = map.get(ImpsConfigNames.CUSTOM_PRESENCE_MAPPING); 131 132 mOthers = map; 133 } 134 135 @Override getProtocolName()136 public String getProtocolName() { 137 return "IMPS"; 138 } 139 setupVersionStrings()140 private void setupVersionStrings() { 141 if (mImpsVersion == ImpsVersion.IMPS_VERSION_11) { 142 if (mDataEncoding == EncodingType.XML) { 143 mContentType = "application/vnd.wv.csp.xml"; 144 } else if (mDataEncoding == EncodingType.WBXML) { 145 mContentType = "application/vnd.wv.csp.wbxml"; 146 } else if (mDataEncoding == EncodingType.SMS) { 147 mContentType = "application/vnd.wv.csp.sms"; 148 } 149 mVersionNs = ImpsConstants.VERSION_11_NS; 150 mTransactionNs = ImpsConstants.TRANSACTION_11_NS; 151 mPresenceNs = ImpsConstants.PRESENCE_11_NS; 152 } else if (mImpsVersion == ImpsVersion.IMPS_VERSION_12) { 153 if (mDataEncoding == EncodingType.XML) { 154 mContentType = "application/vnd.wv.csp.xml"; 155 } else if (mDataEncoding == EncodingType.WBXML) { 156 mContentType = "application/vnd.wv.csp.wbxml"; 157 } else if (mDataEncoding == EncodingType.SMS) { 158 mContentType = "application/vnd.wv.csp.sms"; 159 } 160 161 mVersionNs = ImpsConstants.VERSION_12_NS; 162 mTransactionNs = ImpsConstants.TRANSACTION_12_NS; 163 mPresenceNs = ImpsConstants.PRESENCE_12_NS; 164 } else if (mImpsVersion == ImpsVersion.IMPS_VERSION_13){ 165 if (mDataEncoding == EncodingType.XML) { 166 mContentType = "application/vnd.wv.csp+xml"; 167 } else if (mDataEncoding == EncodingType.WBXML) { 168 mContentType = "application/vnd.wv.csp+wbxml"; 169 } else if (mDataEncoding == EncodingType.SMS) { 170 mContentType = "application/vnd.wv.csp.sms"; 171 } 172 173 mVersionNs = ImpsConstants.VERSION_13_NS; 174 mTransactionNs = ImpsConstants.TRANSACTION_13_NS; 175 mPresenceNs = ImpsConstants.PRESENCE_13_NS; 176 } 177 } 178 getClientId()179 public String getClientId() { 180 return mClientId; 181 } 182 getMsisdn()183 public String getMsisdn() { 184 return mMsisdn; 185 } 186 use4wayLogin()187 public boolean use4wayLogin() { 188 return mSecureLogin; 189 } 190 useSmsAuth()191 public boolean useSmsAuth() { 192 return isTrue(mOthers.get(ImpsConfigNames.SMS_AUTH)); 193 } 194 needDeliveryReport()195 public boolean needDeliveryReport() { 196 return NEED_DELIVERY_REPORT; 197 } 198 199 /** 200 * Gets the type of protocol binding for data channel. 201 * 202 * @return the type of protocol binding for data channel. 203 */ getDataChannelBinding()204 public TransportType getDataChannelBinding() { 205 return mDataChannelBinding; 206 } 207 208 /** 209 * Gets the type of protocol binding for CIR channel. 210 * 211 * @return the type of protocol binding for CIR channel. 212 */ getCirChannelBinding()213 public CirMethod getCirChannelBinding() { 214 return mCirChannelBinding; 215 } 216 217 /** 218 * Gets the host name of the server. 219 * 220 * @return the host name of the server. 221 */ getHost()222 public String getHost() { 223 return mHost; 224 } 225 226 /** 227 * Sets the host name of the server. 228 * 229 * @param host the host name. 230 */ setHost(String host)231 public void setHost(String host) { 232 mHost = host; 233 } 234 235 /** 236 * Gets the number of milliseconds to wait for a response from the server. 237 * The default value is 45 seconds. 238 * 239 * @return the milliseconds to wait for a response from the server 240 */ getReplyTimeout()241 public int getReplyTimeout() { 242 return mReplyTimeout; 243 } 244 245 /** 246 * XXX: Workaround for the OZ IMPS GTalk server which supports only basic 247 * presence attributes and don't support GetAttributeList. 248 * 249 * @return <code>true</code> if only basic presence attribute is 250 * supported. 251 */ supportBasicPresenceOnly()252 public boolean supportBasicPresenceOnly() { 253 return mBasicPresenceOnly; 254 } 255 getTransportContentType()256 public String getTransportContentType() { 257 return mContentType; 258 } 259 getImpsVersion()260 public ImpsVersion getImpsVersion() { 261 return mImpsVersion; 262 } 263 264 // TODO: should remove this and let the serializer to handle all the name 265 // spaces. getPresenceNs()266 public String getPresenceNs() { 267 return mPresenceNs; 268 } 269 createPrimitiveParser()270 public PrimitiveParser createPrimitiveParser() throws ImException { 271 if(mDataEncoding == EncodingType.WBXML) { 272 return new WbxmlPrimitiveParser(); 273 } else if (mDataEncoding == EncodingType.XML) { 274 return new XmlPrimitiveParser(); 275 } else if (mDataEncoding == EncodingType.SMS) { 276 return new PtsPrimitiveParser(); 277 } 278 279 ImpsLog.log("Unknown DataEncoding: " + mDataEncoding); 280 return null; 281 } 282 createPrimitiveSerializer()283 public PrimitiveSerializer createPrimitiveSerializer() { 284 if(mDataEncoding == EncodingType.WBXML) { 285 return new WbxmlPrimitiveSerializer(mImpsVersion, 286 mVersionNs, mTransactionNs); 287 } else if (mDataEncoding == EncodingType.XML) { 288 return new XmlPrimitiveSerializer(mVersionNs, mTransactionNs); 289 } else if (mDataEncoding == EncodingType.SMS) { 290 try { 291 return new PtsPrimitiveSerializer(mImpsVersion); 292 } catch (SerializerException e) { 293 ImpsLog.logError(e); 294 return null; 295 } 296 } 297 298 ImpsLog.log("Unknown DataEncoding: " + mDataEncoding); 299 return null; 300 } 301 302 /** 303 * Gets the port number for the standalone UDP/IP CIR method. This is only 304 * useful when UDP CIR method is used. The default port number is 3717. 305 * 306 * @return the port number for the standalone UDP/IP CIR method. 307 */ getUdpPort()308 public int getUdpPort() { 309 return mUdpPort; 310 } 311 getSmsAddr()312 public String getSmsAddr() { 313 return mOthers.get(ImpsConfigNames.SMS_ADDR); 314 } 315 getSmsPort()316 public int getSmsPort() { 317 String value = mOthers.get(ImpsConfigNames.SMS_PORT); 318 if (value == null) { 319 return DEFAULT_SMS_PORT; 320 } 321 try { 322 return Integer.parseInt(value); 323 } catch (NumberFormatException e) { 324 return DEFAULT_SMS_PORT; 325 } 326 } 327 getSmsCirAddr()328 public String getSmsCirAddr() { 329 return mOthers.get(ImpsConfigNames.SMS_CIR_ADDR); 330 } 331 getSmsCirPort()332 public int getSmsCirPort() { 333 String value = mOthers.get(ImpsConfigNames.SMS_CIR_PORT); 334 if (value == null) { 335 return DEFAULT_SMS_CIR_PORT; 336 } 337 try { 338 return Integer.parseInt(value); 339 } catch (NumberFormatException e) { 340 return DEFAULT_SMS_CIR_PORT; 341 } 342 } 343 usePrensencePolling()344 public boolean usePrensencePolling() { 345 String value = mOthers.get(ImpsConfigNames.POLL_PRESENCE); 346 return isTrue(value); 347 } 348 getPresencePollInterval()349 public long getPresencePollInterval() { 350 String value = mOthers.get(ImpsConfigNames.PRESENCE_POLLING_INTERVAL); 351 if (value == null) { 352 return DEFAULT_PRESENCE_POLL_INTERVAL; 353 } 354 try { 355 return Long.parseLong(value); 356 } catch (NumberFormatException e) { 357 return DEFAULT_PRESENCE_POLL_INTERVAL; 358 } 359 } 360 getDefaultServerPollMin()361 public int getDefaultServerPollMin() { 362 return DEFAULT_MIN_SERVER_POLL; 363 } 364 getDefaultKeepAliveInterval()365 public int getDefaultKeepAliveInterval() { 366 return DEFAULT_KEEPALIVE_SECONDS; 367 } 368 getPresenceMapping()369 public PresenceMapping getPresenceMapping() { 370 if (mPresenceMapping != null) { 371 return mPresenceMapping; 372 } 373 374 if (mCustomPresenceMapping != null) { 375 try { 376 mPresenceMapping = new CustomPresenceMapping(mPluginPath, 377 mCustomPresenceMapping); 378 } catch (ImException e) { 379 ImpsLog.logError("Failed to load custom presence mapping", e); 380 } 381 } 382 383 if (mPresenceMapping == null) { 384 mPresenceMapping = new DefaultPresenceMapping(); 385 } 386 return mPresenceMapping; 387 } 388 getPasswordDigest()389 public PasswordDigest getPasswordDigest() { 390 if (mPasswordDigest != null) { 391 return mPasswordDigest; 392 } 393 394 if (mCustomPasswordDigest != null) { 395 try { 396 mPasswordDigest = new CustomPasswordDigest(mPluginPath, mCustomPasswordDigest); 397 } catch (ImException e) { 398 ImpsLog.logError("Can't load custom password digest method", e); 399 } 400 } 401 402 if (mPasswordDigest == null) { 403 mPasswordDigest = new StandardPasswordDigest(); 404 } 405 return mPasswordDigest; 406 } 407 getDefaultDomain()408 public String getDefaultDomain() { 409 return mDefaultDomain; 410 } 411 isTrue(String value)412 private boolean isTrue(String value) { 413 return "true".equalsIgnoreCase(value); 414 } 415 416 /** 417 * Represents the type of protocol binding for data channel. 418 */ 419 public static enum TransportType { 420 WAP, HTTP, HTTPS, SMS, 421 } 422 423 /** 424 * Represents the type of the data encoding. 425 */ 426 public static enum EncodingType { 427 XML, WBXML, SMS, 428 } 429 430 /** 431 * Represents the type of protocol binding for CIR channel. 432 */ 433 public static enum CirMethod { 434 /** 435 * WAP 1.2 or WAP 2.0 push using WSP unit push message and SMS as a 436 * bearer 437 */ 438 WAPSMS, 439 440 /** 441 * WAP 1.2 or WAP 2.0 push using WSP unit push message and UDP/IP as a 442 * bearer 443 */ 444 WAPUDP, 445 446 /** 447 * Standalone SMS binding 448 */ 449 SSMS, 450 451 /** 452 * Standalone UDP/IP binding 453 */ 454 SUDP, 455 456 /** 457 * Standalone TCP/IP binding 458 */ 459 STCP, 460 461 /** 462 * Standalone HTTP binding 463 */ 464 SHTTP, 465 466 /** 467 * No CIR channel 468 */ 469 NONE, 470 } 471 } 472