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.os.Parcel; 20 import android.os.Parcelable; 21 import android.text.TextUtils; 22 23 import java.io.Serializable; 24 import java.text.ParseException; 25 import javax.sip.InvalidArgumentException; 26 import javax.sip.ListeningPoint; 27 import javax.sip.PeerUnavailableException; 28 import javax.sip.SipFactory; 29 import javax.sip.address.Address; 30 import javax.sip.address.AddressFactory; 31 import javax.sip.address.SipURI; 32 import javax.sip.address.URI; 33 34 /** 35 * Defines a SIP profile, including a SIP account, domain and server information. 36 * <p>You can create a {@link SipProfile} using {@link 37 * SipProfile.Builder}. You can also retrieve one from a {@link SipSession}, using {@link 38 * SipSession#getLocalProfile} and {@link SipSession#getPeerProfile}.</p> 39 */ 40 public class SipProfile implements Parcelable, Serializable, Cloneable { 41 private static final long serialVersionUID = 1L; 42 private static final int DEFAULT_PORT = 5060; 43 private Address mAddress; 44 private String mProxyAddress; 45 private String mPassword; 46 private String mDomain; 47 private String mProtocol = ListeningPoint.UDP; 48 private String mProfileName; 49 private boolean mSendKeepAlive = false; 50 private boolean mAutoRegistration = true; 51 private transient int mCallingUid = 0; 52 53 public static final Parcelable.Creator<SipProfile> CREATOR = 54 new Parcelable.Creator<SipProfile>() { 55 public SipProfile createFromParcel(Parcel in) { 56 return new SipProfile(in); 57 } 58 59 public SipProfile[] newArray(int size) { 60 return new SipProfile[size]; 61 } 62 }; 63 64 /** 65 * Helper class for creating a {@link SipProfile}. 66 */ 67 public static class Builder { 68 private AddressFactory mAddressFactory; 69 private SipProfile mProfile = new SipProfile(); 70 private SipURI mUri; 71 private String mDisplayName; 72 private String mProxyAddress; 73 74 { 75 try { 76 mAddressFactory = 77 SipFactory.getInstance().createAddressFactory(); 78 } catch (PeerUnavailableException e) { 79 throw new RuntimeException(e); 80 } 81 } 82 83 /** 84 * Creates a builder based on the given profile. 85 */ 86 public Builder(SipProfile profile) { 87 if (profile == null) throw new NullPointerException(); 88 try { 89 mProfile = (SipProfile) profile.clone(); 90 } catch (CloneNotSupportedException e) { 91 throw new RuntimeException("should not occur", e); 92 } 93 mProfile.mAddress = null; 94 mUri = profile.getUri(); 95 mUri.setUserPassword(profile.getPassword()); 96 mDisplayName = profile.getDisplayName(); 97 mProxyAddress = profile.getProxyAddress(); 98 } 99 100 /** 101 * Constructor. 102 * 103 * @param uriString the URI string as "sip:<user_name>@<domain>" 104 * @throws ParseException if the string is not a valid URI 105 */ 106 public Builder(String uriString) throws ParseException { 107 if (uriString == null) { 108 throw new NullPointerException("uriString cannot be null"); 109 } 110 URI uri = mAddressFactory.createURI(fix(uriString)); 111 if (uri instanceof SipURI) { 112 mUri = (SipURI) uri; 113 } else { 114 throw new ParseException(uriString + " is not a SIP URI", 0); 115 } 116 mProfile.mDomain = mUri.getHost(); 117 } 118 119 /** 120 * Constructor. 121 * 122 * @param username username of the SIP account 123 * @param serverDomain the SIP server domain; if the network address 124 * is different from the domain, use {@link #setOutboundProxy} to 125 * set server address 126 * @throws ParseException if the parameters are not valid 127 */ 128 public Builder(String username, String serverDomain) 129 throws ParseException { 130 if ((username == null) || (serverDomain == null)) { 131 throw new NullPointerException( 132 "username and serverDomain cannot be null"); 133 } 134 mUri = mAddressFactory.createSipURI(username, serverDomain); 135 mProfile.mDomain = serverDomain; 136 } 137 138 private String fix(String uriString) { 139 return (uriString.trim().toLowerCase().startsWith("sip:") 140 ? uriString 141 : "sip:" + uriString); 142 } 143 144 /** 145 * Sets the name of the profile. This name is given by user. 146 * 147 * @param name name of the profile 148 * @return this builder object 149 */ 150 public Builder setProfileName(String name) { 151 mProfile.mProfileName = name; 152 return this; 153 } 154 155 /** 156 * Sets the password of the SIP account 157 * 158 * @param password password of the SIP account 159 * @return this builder object 160 */ 161 public Builder setPassword(String password) { 162 mUri.setUserPassword(password); 163 return this; 164 } 165 166 /** 167 * Sets the port number of the server. By default, it is 5060. 168 * 169 * @param port port number of the server 170 * @return this builder object 171 * @throws IllegalArgumentException if the port number is out of range 172 */ 173 public Builder setPort(int port) throws IllegalArgumentException { 174 try { 175 mUri.setPort(port); 176 return this; 177 } catch (InvalidArgumentException e) { 178 throw new IllegalArgumentException(e); 179 } 180 } 181 182 /** 183 * Sets the protocol used to connect to the SIP server. Currently, 184 * only "UDP" and "TCP" are supported. 185 * 186 * @param protocol the protocol string 187 * @return this builder object 188 * @throws IllegalArgumentException if the protocol is not recognized 189 */ 190 public Builder setProtocol(String protocol) 191 throws IllegalArgumentException { 192 if (protocol == null) { 193 throw new NullPointerException("protocol cannot be null"); 194 } 195 protocol = protocol.toUpperCase(); 196 if (!protocol.equals("UDP") && !protocol.equals("TCP")) { 197 throw new IllegalArgumentException( 198 "unsupported protocol: " + protocol); 199 } 200 mProfile.mProtocol = protocol; 201 return this; 202 } 203 204 /** 205 * Sets the outbound proxy of the SIP server. 206 * 207 * @param outboundProxy the network address of the outbound proxy 208 * @return this builder object 209 */ 210 public Builder setOutboundProxy(String outboundProxy) { 211 mProxyAddress = outboundProxy; 212 return this; 213 } 214 215 /** 216 * Sets the display name of the user. 217 * 218 * @param displayName display name of the user 219 * @return this builder object 220 */ 221 public Builder setDisplayName(String displayName) { 222 mDisplayName = displayName; 223 return this; 224 } 225 226 /** 227 * Sets the send keep-alive flag. 228 * 229 * @param flag true if sending keep-alive message is required, 230 * false otherwise 231 * @return this builder object 232 */ 233 public Builder setSendKeepAlive(boolean flag) { 234 mProfile.mSendKeepAlive = flag; 235 return this; 236 } 237 238 239 /** 240 * Sets the auto. registration flag. 241 * 242 * @param flag true if the profile will be registered automatically, 243 * false otherwise 244 * @return this builder object 245 */ 246 public Builder setAutoRegistration(boolean flag) { 247 mProfile.mAutoRegistration = flag; 248 return this; 249 } 250 251 /** 252 * Builds and returns the SIP profile object. 253 * 254 * @return the profile object created 255 */ 256 public SipProfile build() { 257 // remove password from URI 258 mProfile.mPassword = mUri.getUserPassword(); 259 mUri.setUserPassword(null); 260 try { 261 mProfile.mAddress = mAddressFactory.createAddress( 262 mDisplayName, mUri); 263 if (!TextUtils.isEmpty(mProxyAddress)) { 264 SipURI uri = (SipURI) 265 mAddressFactory.createURI(fix(mProxyAddress)); 266 mProfile.mProxyAddress = uri.getHost(); 267 } 268 } catch (ParseException e) { 269 // must not occur 270 throw new RuntimeException(e); 271 } 272 return mProfile; 273 } 274 } 275 276 private SipProfile() { 277 } 278 279 private SipProfile(Parcel in) { 280 mAddress = (Address) in.readSerializable(); 281 mProxyAddress = in.readString(); 282 mPassword = in.readString(); 283 mDomain = in.readString(); 284 mProtocol = in.readString(); 285 mProfileName = in.readString(); 286 mSendKeepAlive = (in.readInt() == 0) ? false : true; 287 mAutoRegistration = (in.readInt() == 0) ? false : true; 288 mCallingUid = in.readInt(); 289 } 290 291 @Override 292 public void writeToParcel(Parcel out, int flags) { 293 out.writeSerializable(mAddress); 294 out.writeString(mProxyAddress); 295 out.writeString(mPassword); 296 out.writeString(mDomain); 297 out.writeString(mProtocol); 298 out.writeString(mProfileName); 299 out.writeInt(mSendKeepAlive ? 1 : 0); 300 out.writeInt(mAutoRegistration ? 1 : 0); 301 out.writeInt(mCallingUid); 302 } 303 304 @Override 305 public int describeContents() { 306 return 0; 307 } 308 309 /** 310 * Gets the SIP URI of this profile. 311 * 312 * @return the SIP URI of this profile 313 * @hide 314 */ 315 public SipURI getUri() { 316 return (SipURI) mAddress.getURI(); 317 } 318 319 /** 320 * Gets the SIP URI string of this profile. 321 * 322 * @return the SIP URI string of this profile 323 */ 324 public String getUriString() { 325 return mAddress.getURI().toString(); 326 } 327 328 /** 329 * Gets the SIP address of this profile. 330 * 331 * @return the SIP address of this profile 332 * @hide 333 */ 334 public Address getSipAddress() { 335 return mAddress; 336 } 337 338 /** 339 * Gets the display name of the user. 340 * 341 * @return the display name of the user 342 */ 343 public String getDisplayName() { 344 return mAddress.getDisplayName(); 345 } 346 347 /** 348 * Gets the username. 349 * 350 * @return the username 351 */ 352 public String getUserName() { 353 return getUri().getUser(); 354 } 355 356 /** 357 * Gets the password. 358 * 359 * @return the password 360 */ 361 public String getPassword() { 362 return mPassword; 363 } 364 365 /** 366 * Gets the SIP domain. 367 * 368 * @return the SIP domain 369 */ 370 public String getSipDomain() { 371 return mDomain; 372 } 373 374 /** 375 * Gets the port number of the SIP server. 376 * 377 * @return the port number of the SIP server 378 */ 379 public int getPort() { 380 int port = getUri().getPort(); 381 return (port == -1) ? DEFAULT_PORT : port; 382 } 383 384 /** 385 * Gets the protocol used to connect to the server. 386 * 387 * @return the protocol 388 */ 389 public String getProtocol() { 390 return mProtocol; 391 } 392 393 /** 394 * Gets the network address of the server outbound proxy. 395 * 396 * @return the network address of the server outbound proxy 397 */ 398 public String getProxyAddress() { 399 return mProxyAddress; 400 } 401 402 /** 403 * Gets the (user-defined) name of the profile. 404 * 405 * @return name of the profile 406 */ 407 public String getProfileName() { 408 return mProfileName; 409 } 410 411 /** 412 * Gets the flag of 'Sending keep-alive'. 413 * 414 * @return the flag of sending SIP keep-alive messages. 415 */ 416 public boolean getSendKeepAlive() { 417 return mSendKeepAlive; 418 } 419 420 /** 421 * Gets the flag of 'Auto Registration'. 422 * 423 * @return the flag of registering the profile automatically. 424 */ 425 public boolean getAutoRegistration() { 426 return mAutoRegistration; 427 } 428 429 /** 430 * Sets the calling process's Uid in the sip service. 431 * @hide 432 */ 433 public void setCallingUid(int uid) { 434 mCallingUid = uid; 435 } 436 437 /** 438 * Gets the calling process's Uid in the sip settings. 439 * @hide 440 */ 441 public int getCallingUid() { 442 return mCallingUid; 443 } 444 } 445