1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net.sip; 18 19 import android.annotation.SystemApi; 20 import android.os.Parcel; 21 import android.os.Parcelable; 22 import android.text.TextUtils; 23 24 import java.io.ObjectStreamException; 25 import java.io.Serializable; 26 import java.text.ParseException; 27 import javax.sip.InvalidArgumentException; 28 import javax.sip.ListeningPoint; 29 import javax.sip.PeerUnavailableException; 30 import javax.sip.SipFactory; 31 import javax.sip.address.Address; 32 import javax.sip.address.AddressFactory; 33 import javax.sip.address.SipURI; 34 import javax.sip.address.URI; 35 36 /** 37 * Defines a SIP profile, including a SIP account, domain and server information. 38 * <p>You can create a {@link SipProfile} using {@link 39 * SipProfile.Builder}. You can also retrieve one from a {@link SipSession}, using {@link 40 * SipSession#getLocalProfile} and {@link SipSession#getPeerProfile}.</p> 41 * 42 * <div class="special reference"> 43 * <h3>Developer Guides</h3> 44 * <p>For more information about using SIP, read the 45 * <a href="{@docRoot}guide/topics/network/sip.html">Session Initiation Protocol</a> 46 * developer guide.</p> 47 * </div> 48 * @deprecated {@link android.net.sip.SipManager} and associated classes are no longer supported and 49 * should not be used as the basis of future VOIP apps. 50 */ 51 public class SipProfile implements Parcelable, Serializable, Cloneable { 52 private static final long serialVersionUID = 1L; 53 private static final int DEFAULT_PORT = 5060; 54 private static final String TCP = "TCP"; 55 private static final String UDP = "UDP"; 56 private Address mAddress; 57 private String mProxyAddress; 58 private String mPassword; 59 private String mDomain; 60 private String mProtocol = UDP; 61 private String mProfileName; 62 private String mAuthUserName; 63 private int mPort = DEFAULT_PORT; 64 private boolean mSendKeepAlive = false; 65 private boolean mAutoRegistration = true; 66 private transient int mCallingUid = 0; 67 68 public static final Parcelable.Creator<SipProfile> CREATOR = 69 new Parcelable.Creator<SipProfile>() { 70 public SipProfile createFromParcel(Parcel in) { 71 return new SipProfile(in); 72 } 73 74 public SipProfile[] newArray(int size) { 75 return new SipProfile[size]; 76 } 77 }; 78 79 /** 80 * Helper class for creating a {@link SipProfile}. 81 */ 82 public static class Builder { 83 private AddressFactory mAddressFactory; 84 private SipProfile mProfile = new SipProfile(); 85 private SipURI mUri; 86 private String mDisplayName; 87 private String mProxyAddress; 88 89 { 90 try { 91 mAddressFactory = 92 SipFactory.getInstance().createAddressFactory(); 93 } catch (PeerUnavailableException e) { 94 throw new RuntimeException(e); 95 } 96 } 97 98 /** 99 * Creates a builder based on the given profile. 100 */ Builder(SipProfile profile)101 public Builder(SipProfile profile) { 102 if (profile == null) throw new NullPointerException(); 103 try { 104 mProfile = (SipProfile) profile.clone(); 105 } catch (CloneNotSupportedException e) { 106 throw new RuntimeException("should not occur", e); 107 } 108 mProfile.mAddress = null; 109 mUri = profile.getUri(); 110 mUri.setUserPassword(profile.getPassword()); 111 mDisplayName = profile.getDisplayName(); 112 mProxyAddress = profile.getProxyAddress(); 113 mProfile.mPort = profile.getPort(); 114 } 115 116 /** 117 * Constructor. 118 * 119 * @param uriString the URI string as "sip:<user_name>@<domain>" 120 * @throws ParseException if the string is not a valid URI 121 */ Builder(String uriString)122 public Builder(String uriString) throws ParseException { 123 if (uriString == null) { 124 throw new NullPointerException("uriString cannot be null"); 125 } 126 URI uri = mAddressFactory.createURI(fix(uriString)); 127 if (uri instanceof SipURI) { 128 mUri = (SipURI) uri; 129 } else { 130 throw new ParseException(uriString + " is not a SIP URI", 0); 131 } 132 mProfile.mDomain = mUri.getHost(); 133 } 134 135 /** 136 * Constructor. 137 * 138 * @param username username of the SIP account 139 * @param serverDomain the SIP server domain; if the network address 140 * is different from the domain, use {@link #setOutboundProxy} to 141 * set server address 142 * @throws ParseException if the parameters are not valid 143 */ Builder(String username, String serverDomain)144 public Builder(String username, String serverDomain) 145 throws ParseException { 146 if ((username == null) || (serverDomain == null)) { 147 throw new NullPointerException( 148 "username and serverDomain cannot be null"); 149 } 150 mUri = mAddressFactory.createSipURI(username, serverDomain); 151 mProfile.mDomain = serverDomain; 152 } 153 fix(String uriString)154 private String fix(String uriString) { 155 return (uriString.trim().toLowerCase().startsWith("sip:") 156 ? uriString 157 : "sip:" + uriString); 158 } 159 160 /** 161 * Sets the username used for authentication. 162 * 163 * @param name authentication username of the profile 164 * @return this builder object 165 */ setAuthUserName(String name)166 public Builder setAuthUserName(String name) { 167 mProfile.mAuthUserName = name; 168 return this; 169 } 170 171 /** 172 * Sets the name of the profile. This name is given by user. 173 * 174 * @param name name of the profile 175 * @return this builder object 176 */ setProfileName(String name)177 public Builder setProfileName(String name) { 178 mProfile.mProfileName = name; 179 return this; 180 } 181 182 /** 183 * Sets the password of the SIP account 184 * 185 * @param password password of the SIP account 186 * @return this builder object 187 */ setPassword(String password)188 public Builder setPassword(String password) { 189 mUri.setUserPassword(password); 190 return this; 191 } 192 193 /** 194 * Sets the port number of the server. By default, it is 5060. 195 * 196 * @param port port number of the server 197 * @return this builder object 198 * @throws IllegalArgumentException if the port number is out of range 199 */ setPort(int port)200 public Builder setPort(int port) throws IllegalArgumentException { 201 if ((port > 65535) || (port < 1000)) { 202 throw new IllegalArgumentException("incorrect port arugment: " + port); 203 } 204 mProfile.mPort = port; 205 return this; 206 } 207 208 /** 209 * Sets the protocol used to connect to the SIP server. Currently, 210 * only "UDP" and "TCP" are supported. 211 * 212 * @param protocol the protocol string 213 * @return this builder object 214 * @throws IllegalArgumentException if the protocol is not recognized 215 */ setProtocol(String protocol)216 public Builder setProtocol(String protocol) 217 throws IllegalArgumentException { 218 if (protocol == null) { 219 throw new NullPointerException("protocol cannot be null"); 220 } 221 protocol = protocol.toUpperCase(); 222 if (!protocol.equals(UDP) && !protocol.equals(TCP)) { 223 throw new IllegalArgumentException( 224 "unsupported protocol: " + protocol); 225 } 226 mProfile.mProtocol = protocol; 227 return this; 228 } 229 230 /** 231 * Sets the outbound proxy of the SIP server. 232 * 233 * @param outboundProxy the network address of the outbound proxy 234 * @return this builder object 235 */ setOutboundProxy(String outboundProxy)236 public Builder setOutboundProxy(String outboundProxy) { 237 mProxyAddress = outboundProxy; 238 return this; 239 } 240 241 /** 242 * Sets the display name of the user. 243 * 244 * @param displayName display name of the user 245 * @return this builder object 246 */ setDisplayName(String displayName)247 public Builder setDisplayName(String displayName) { 248 mDisplayName = displayName; 249 return this; 250 } 251 252 /** 253 * Sets the send keep-alive flag. 254 * 255 * @param flag true if sending keep-alive message is required, 256 * false otherwise 257 * @return this builder object 258 */ setSendKeepAlive(boolean flag)259 public Builder setSendKeepAlive(boolean flag) { 260 mProfile.mSendKeepAlive = flag; 261 return this; 262 } 263 264 265 /** 266 * Sets the auto. registration flag. 267 * 268 * @param flag true if the profile will be registered automatically, 269 * false otherwise 270 * @return this builder object 271 */ setAutoRegistration(boolean flag)272 public Builder setAutoRegistration(boolean flag) { 273 mProfile.mAutoRegistration = flag; 274 return this; 275 } 276 277 /** 278 * Builds and returns the SIP profile object. 279 * 280 * @return the profile object created 281 */ build()282 public SipProfile build() { 283 // remove password from URI 284 mProfile.mPassword = mUri.getUserPassword(); 285 mUri.setUserPassword(null); 286 try { 287 if (!TextUtils.isEmpty(mProxyAddress)) { 288 SipURI uri = (SipURI) 289 mAddressFactory.createURI(fix(mProxyAddress)); 290 mProfile.mProxyAddress = uri.getHost(); 291 } else { 292 if (!mProfile.mProtocol.equals(UDP)) { 293 mUri.setTransportParam(mProfile.mProtocol); 294 } 295 if (mProfile.mPort != DEFAULT_PORT) { 296 mUri.setPort(mProfile.mPort); 297 } 298 } 299 mProfile.mAddress = mAddressFactory.createAddress( 300 mDisplayName, mUri); 301 } catch (InvalidArgumentException e) { 302 throw new RuntimeException(e); 303 } catch (ParseException e) { 304 // must not occur 305 throw new RuntimeException(e); 306 } 307 return mProfile; 308 } 309 } 310 SipProfile()311 private SipProfile() { 312 } 313 SipProfile(Parcel in)314 private SipProfile(Parcel in) { 315 mAddress = (Address) in.readSerializable(); 316 mProxyAddress = in.readString(); 317 mPassword = in.readString(); 318 mDomain = in.readString(); 319 mProtocol = in.readString(); 320 mProfileName = in.readString(); 321 mSendKeepAlive = (in.readInt() == 0) ? false : true; 322 mAutoRegistration = (in.readInt() == 0) ? false : true; 323 mCallingUid = in.readInt(); 324 mPort = in.readInt(); 325 mAuthUserName = in.readString(); 326 } 327 328 @Override writeToParcel(Parcel out, int flags)329 public void writeToParcel(Parcel out, int flags) { 330 out.writeSerializable(mAddress); 331 out.writeString(mProxyAddress); 332 out.writeString(mPassword); 333 out.writeString(mDomain); 334 out.writeString(mProtocol); 335 out.writeString(mProfileName); 336 out.writeInt(mSendKeepAlive ? 1 : 0); 337 out.writeInt(mAutoRegistration ? 1 : 0); 338 out.writeInt(mCallingUid); 339 out.writeInt(mPort); 340 out.writeString(mAuthUserName); 341 } 342 343 @Override describeContents()344 public int describeContents() { 345 return 0; 346 } 347 348 /** 349 * Gets the SIP URI of this profile. 350 * 351 * @return the SIP URI of this profile 352 * @hide 353 */ getUri()354 public SipURI getUri() { 355 return (SipURI) mAddress.getURI(); 356 } 357 358 /** 359 * Gets the SIP URI string of this profile. 360 * 361 * @return the SIP URI string of this profile 362 */ getUriString()363 public String getUriString() { 364 // We need to return the sip uri domain instead of 365 // the SIP URI with transport, port information if 366 // the outbound proxy address exists. 367 if (!TextUtils.isEmpty(mProxyAddress)) { 368 return "sip:" + getUserName() + "@" + mDomain; 369 } 370 return getUri().toString(); 371 } 372 373 /** 374 * Gets the SIP address of this profile. 375 * 376 * @return the SIP address of this profile 377 * @hide 378 */ getSipAddress()379 public Address getSipAddress() { 380 return mAddress; 381 } 382 383 /** 384 * Gets the display name of the user. 385 * 386 * @return the display name of the user 387 */ getDisplayName()388 public String getDisplayName() { 389 return mAddress.getDisplayName(); 390 } 391 392 /** 393 * Gets the username. 394 * 395 * @return the username 396 */ getUserName()397 public String getUserName() { 398 return getUri().getUser(); 399 } 400 401 /** 402 * Gets the username for authentication. If it is null, then the username 403 * is used in authentication instead. 404 * 405 * @return the authentication username 406 * @see #getUserName 407 */ getAuthUserName()408 public String getAuthUserName() { 409 return mAuthUserName; 410 } 411 412 /** 413 * Gets the password. 414 * 415 * @return the password 416 */ getPassword()417 public String getPassword() { 418 return mPassword; 419 } 420 421 /** 422 * Gets the SIP domain. 423 * 424 * @return the SIP domain 425 */ getSipDomain()426 public String getSipDomain() { 427 return mDomain; 428 } 429 430 /** 431 * Gets the port number of the SIP server. 432 * 433 * @return the port number of the SIP server 434 */ getPort()435 public int getPort() { 436 return mPort; 437 } 438 439 /** 440 * Gets the protocol used to connect to the server. 441 * 442 * @return the protocol 443 */ getProtocol()444 public String getProtocol() { 445 return mProtocol; 446 } 447 448 /** 449 * Gets the network address of the server outbound proxy. 450 * 451 * @return the network address of the server outbound proxy 452 */ getProxyAddress()453 public String getProxyAddress() { 454 return mProxyAddress; 455 } 456 457 /** 458 * Gets the (user-defined) name of the profile. 459 * 460 * @return name of the profile 461 */ getProfileName()462 public String getProfileName() { 463 return mProfileName; 464 } 465 466 /** 467 * Gets the flag of 'Sending keep-alive'. 468 * 469 * @return the flag of sending SIP keep-alive messages. 470 */ getSendKeepAlive()471 public boolean getSendKeepAlive() { 472 return mSendKeepAlive; 473 } 474 475 /** 476 * Gets the flag of 'Auto Registration'. 477 * 478 * @return the flag of registering the profile automatically. 479 */ getAutoRegistration()480 public boolean getAutoRegistration() { 481 return mAutoRegistration; 482 } 483 484 /** 485 * Sets the calling process's Uid in the sip service. 486 */ setCallingUid(int uid)487 public void setCallingUid(int uid) { 488 mCallingUid = uid; 489 } 490 491 /** 492 * Gets the calling process's Uid in the sip settings. 493 * 494 * @return the calling process's Uid in the sip settings. 495 * @hide 496 */ 497 @SystemApi getCallingUid()498 public int getCallingUid() { 499 return mCallingUid; 500 } 501 readResolve()502 private Object readResolve() throws ObjectStreamException { 503 // For compatibility. 504 if (mPort == 0) mPort = DEFAULT_PORT; 505 return this; 506 } 507 } 508