blob: 0ef754ce4ef8cfdcd002a6c962b3803d621fa337 [file] [log] [blame]
Chung-yih Wang363c2ab2010-08-05 10:21:20 +08001/*
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
17package android.net.sip;
18
19import android.os.Parcel;
20import android.os.Parcelable;
21import android.text.TextUtils;
22
Chung-yih Wangf0532922010-11-03 13:11:53 +080023import java.io.ObjectStreamException;
Chung-yih Wang363c2ab2010-08-05 10:21:20 +080024import java.io.Serializable;
25import java.text.ParseException;
26import javax.sip.InvalidArgumentException;
27import javax.sip.ListeningPoint;
28import javax.sip.PeerUnavailableException;
29import javax.sip.SipFactory;
30import javax.sip.address.Address;
31import javax.sip.address.AddressFactory;
32import javax.sip.address.SipURI;
33import javax.sip.address.URI;
34
35/**
Scott Main02b1d682010-10-22 11:29:57 -070036 * Defines a SIP profile, including a SIP account, domain and server information.
37 * <p>You can create a {@link SipProfile} using {@link
38 * SipProfile.Builder}. You can also retrieve one from a {@link SipSession}, using {@link
39 * SipSession#getLocalProfile} and {@link SipSession#getPeerProfile}.</p>
Joe Fernandez3aef8e1d2011-12-20 10:38:34 -080040 *
41 * <div class="special reference">
42 * <h3>Developer Guides</h3>
43 * <p>For more information about using SIP, read the
44 * <a href="{@docRoot}guide/topics/network/sip.html">Session Initiation Protocol</a>
45 * developer guide.</p>
46 * </div>
Chung-yih Wang363c2ab2010-08-05 10:21:20 +080047 */
Hung-ying Tyancf95f5d2010-08-23 21:36:14 +080048public class SipProfile implements Parcelable, Serializable, Cloneable {
Chung-yih Wang363c2ab2010-08-05 10:21:20 +080049 private static final long serialVersionUID = 1L;
50 private static final int DEFAULT_PORT = 5060;
Chung-yih Wangf0532922010-11-03 13:11:53 +080051 private static final String TCP = "TCP";
52 private static final String UDP = "UDP";
Chung-yih Wang363c2ab2010-08-05 10:21:20 +080053 private Address mAddress;
54 private String mProxyAddress;
55 private String mPassword;
56 private String mDomain;
Chung-yih Wangf0532922010-11-03 13:11:53 +080057 private String mProtocol = UDP;
Chung-yih Wang363c2ab2010-08-05 10:21:20 +080058 private String mProfileName;
Chung-yih Wang0f7de882011-01-06 18:44:43 +080059 private String mAuthUserName;
Chung-yih Wangf0532922010-11-03 13:11:53 +080060 private int mPort = DEFAULT_PORT;
Chung-yih Wang363c2ab2010-08-05 10:21:20 +080061 private boolean mSendKeepAlive = false;
62 private boolean mAutoRegistration = true;
Hung-ying Tyan60264b302010-09-01 09:15:10 +080063 private transient int mCallingUid = 0;
Chung-yih Wang363c2ab2010-08-05 10:21:20 +080064
Chung-yih Wang363c2ab2010-08-05 10:21:20 +080065 public static final Parcelable.Creator<SipProfile> CREATOR =
66 new Parcelable.Creator<SipProfile>() {
67 public SipProfile createFromParcel(Parcel in) {
68 return new SipProfile(in);
69 }
70
71 public SipProfile[] newArray(int size) {
72 return new SipProfile[size];
73 }
74 };
75
76 /**
Scott Main02b1d682010-10-22 11:29:57 -070077 * Helper class for creating a {@link SipProfile}.
Chung-yih Wang363c2ab2010-08-05 10:21:20 +080078 */
79 public static class Builder {
80 private AddressFactory mAddressFactory;
81 private SipProfile mProfile = new SipProfile();
82 private SipURI mUri;
83 private String mDisplayName;
84 private String mProxyAddress;
85
86 {
87 try {
88 mAddressFactory =
89 SipFactory.getInstance().createAddressFactory();
90 } catch (PeerUnavailableException e) {
91 throw new RuntimeException(e);
92 }
93 }
94
95 /**
Hung-ying Tyancf95f5d2010-08-23 21:36:14 +080096 * Creates a builder based on the given profile.
97 */
98 public Builder(SipProfile profile) {
99 if (profile == null) throw new NullPointerException();
100 try {
101 mProfile = (SipProfile) profile.clone();
102 } catch (CloneNotSupportedException e) {
103 throw new RuntimeException("should not occur", e);
104 }
105 mProfile.mAddress = null;
106 mUri = profile.getUri();
107 mUri.setUserPassword(profile.getPassword());
108 mDisplayName = profile.getDisplayName();
109 mProxyAddress = profile.getProxyAddress();
Chung-yih Wangf0532922010-11-03 13:11:53 +0800110 mProfile.mPort = profile.getPort();
Hung-ying Tyancf95f5d2010-08-23 21:36:14 +0800111 }
112
113 /**
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800114 * Constructor.
115 *
116 * @param uriString the URI string as "sip:<user_name>@<domain>"
117 * @throws ParseException if the string is not a valid URI
118 */
119 public Builder(String uriString) throws ParseException {
120 if (uriString == null) {
121 throw new NullPointerException("uriString cannot be null");
122 }
123 URI uri = mAddressFactory.createURI(fix(uriString));
124 if (uri instanceof SipURI) {
125 mUri = (SipURI) uri;
126 } else {
127 throw new ParseException(uriString + " is not a SIP URI", 0);
128 }
129 mProfile.mDomain = mUri.getHost();
130 }
131
132 /**
133 * Constructor.
134 *
135 * @param username username of the SIP account
136 * @param serverDomain the SIP server domain; if the network address
Hung-ying Tyan286bb5a2010-09-14 20:43:54 +0800137 * is different from the domain, use {@link #setOutboundProxy} to
138 * set server address
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800139 * @throws ParseException if the parameters are not valid
140 */
141 public Builder(String username, String serverDomain)
142 throws ParseException {
143 if ((username == null) || (serverDomain == null)) {
144 throw new NullPointerException(
145 "username and serverDomain cannot be null");
146 }
147 mUri = mAddressFactory.createSipURI(username, serverDomain);
148 mProfile.mDomain = serverDomain;
149 }
150
151 private String fix(String uriString) {
152 return (uriString.trim().toLowerCase().startsWith("sip:")
153 ? uriString
154 : "sip:" + uriString);
155 }
156
157 /**
Chung-yih Wang0f7de882011-01-06 18:44:43 +0800158 * Sets the username used for authentication.
159 *
Chung-yih Wang9e25df42011-02-10 15:20:41 +0800160 * @param name authentication username of the profile
Chung-yih Wang0f7de882011-01-06 18:44:43 +0800161 * @return this builder object
Chung-yih Wang0f7de882011-01-06 18:44:43 +0800162 */
163 public Builder setAuthUserName(String name) {
164 mProfile.mAuthUserName = name;
165 return this;
166 }
167
168 /**
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800169 * Sets the name of the profile. This name is given by user.
170 *
171 * @param name name of the profile
172 * @return this builder object
173 */
174 public Builder setProfileName(String name) {
175 mProfile.mProfileName = name;
176 return this;
177 }
178
179 /**
180 * Sets the password of the SIP account
181 *
182 * @param password password of the SIP account
183 * @return this builder object
184 */
185 public Builder setPassword(String password) {
186 mUri.setUserPassword(password);
187 return this;
188 }
189
190 /**
191 * Sets the port number of the server. By default, it is 5060.
192 *
193 * @param port port number of the server
194 * @return this builder object
Hung-ying Tyan99bf4e42010-09-14 20:12:59 +0800195 * @throws IllegalArgumentException if the port number is out of range
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800196 */
Hung-ying Tyan99bf4e42010-09-14 20:12:59 +0800197 public Builder setPort(int port) throws IllegalArgumentException {
Chung-yih Wangf0532922010-11-03 13:11:53 +0800198 if ((port > 65535) || (port < 1000)) {
Hung-ying Tyaneecf4a62010-12-16 16:13:29 +0800199 throw new IllegalArgumentException("incorrect port arugment: " + port);
Hung-ying Tyan99bf4e42010-09-14 20:12:59 +0800200 }
Chung-yih Wangf0532922010-11-03 13:11:53 +0800201 mProfile.mPort = port;
202 return this;
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800203 }
204
205 /**
206 * Sets the protocol used to connect to the SIP server. Currently,
207 * only "UDP" and "TCP" are supported.
208 *
209 * @param protocol the protocol string
210 * @return this builder object
Hung-ying Tyan99bf4e42010-09-14 20:12:59 +0800211 * @throws IllegalArgumentException if the protocol is not recognized
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800212 */
213 public Builder setProtocol(String protocol)
Hung-ying Tyan99bf4e42010-09-14 20:12:59 +0800214 throws IllegalArgumentException {
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800215 if (protocol == null) {
216 throw new NullPointerException("protocol cannot be null");
217 }
218 protocol = protocol.toUpperCase();
Chung-yih Wangf0532922010-11-03 13:11:53 +0800219 if (!protocol.equals(UDP) && !protocol.equals(TCP)) {
Hung-ying Tyan99bf4e42010-09-14 20:12:59 +0800220 throw new IllegalArgumentException(
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800221 "unsupported protocol: " + protocol);
222 }
223 mProfile.mProtocol = protocol;
224 return this;
225 }
226
227 /**
228 * Sets the outbound proxy of the SIP server.
229 *
230 * @param outboundProxy the network address of the outbound proxy
231 * @return this builder object
232 */
233 public Builder setOutboundProxy(String outboundProxy) {
234 mProxyAddress = outboundProxy;
235 return this;
236 }
237
238 /**
239 * Sets the display name of the user.
240 *
241 * @param displayName display name of the user
242 * @return this builder object
243 */
244 public Builder setDisplayName(String displayName) {
245 mDisplayName = displayName;
246 return this;
247 }
248
249 /**
250 * Sets the send keep-alive flag.
251 *
252 * @param flag true if sending keep-alive message is required,
253 * false otherwise
254 * @return this builder object
255 */
256 public Builder setSendKeepAlive(boolean flag) {
257 mProfile.mSendKeepAlive = flag;
258 return this;
259 }
260
261
262 /**
263 * Sets the auto. registration flag.
264 *
265 * @param flag true if the profile will be registered automatically,
266 * false otherwise
267 * @return this builder object
268 */
269 public Builder setAutoRegistration(boolean flag) {
270 mProfile.mAutoRegistration = flag;
271 return this;
272 }
273
274 /**
275 * Builds and returns the SIP profile object.
276 *
277 * @return the profile object created
278 */
279 public SipProfile build() {
280 // remove password from URI
281 mProfile.mPassword = mUri.getUserPassword();
282 mUri.setUserPassword(null);
283 try {
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800284 if (!TextUtils.isEmpty(mProxyAddress)) {
285 SipURI uri = (SipURI)
286 mAddressFactory.createURI(fix(mProxyAddress));
287 mProfile.mProxyAddress = uri.getHost();
Chung-yih Wangf0532922010-11-03 13:11:53 +0800288 } else {
289 if (!mProfile.mProtocol.equals(UDP)) {
290 mUri.setTransportParam(mProfile.mProtocol);
291 }
292 if (mProfile.mPort != DEFAULT_PORT) {
293 mUri.setPort(mProfile.mPort);
294 }
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800295 }
Chung-yih Wangf0532922010-11-03 13:11:53 +0800296 mProfile.mAddress = mAddressFactory.createAddress(
297 mDisplayName, mUri);
298 } catch (InvalidArgumentException e) {
299 throw new RuntimeException(e);
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800300 } catch (ParseException e) {
301 // must not occur
302 throw new RuntimeException(e);
303 }
304 return mProfile;
305 }
306 }
307
308 private SipProfile() {
309 }
310
311 private SipProfile(Parcel in) {
312 mAddress = (Address) in.readSerializable();
313 mProxyAddress = in.readString();
314 mPassword = in.readString();
315 mDomain = in.readString();
316 mProtocol = in.readString();
317 mProfileName = in.readString();
318 mSendKeepAlive = (in.readInt() == 0) ? false : true;
319 mAutoRegistration = (in.readInt() == 0) ? false : true;
Chung-yih Wang5424c8d2010-08-25 19:02:18 +0800320 mCallingUid = in.readInt();
Chung-yih Wangf0532922010-11-03 13:11:53 +0800321 mPort = in.readInt();
Chung-yih Wang0f7de882011-01-06 18:44:43 +0800322 mAuthUserName = in.readString();
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800323 }
324
Hung-ying Tyan84a357b2010-09-16 04:11:32 +0800325 @Override
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800326 public void writeToParcel(Parcel out, int flags) {
327 out.writeSerializable(mAddress);
328 out.writeString(mProxyAddress);
329 out.writeString(mPassword);
330 out.writeString(mDomain);
331 out.writeString(mProtocol);
332 out.writeString(mProfileName);
333 out.writeInt(mSendKeepAlive ? 1 : 0);
334 out.writeInt(mAutoRegistration ? 1 : 0);
Chung-yih Wang5424c8d2010-08-25 19:02:18 +0800335 out.writeInt(mCallingUid);
Chung-yih Wangf0532922010-11-03 13:11:53 +0800336 out.writeInt(mPort);
Chung-yih Wang0f7de882011-01-06 18:44:43 +0800337 out.writeString(mAuthUserName);
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800338 }
339
Hung-ying Tyan84a357b2010-09-16 04:11:32 +0800340 @Override
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800341 public int describeContents() {
342 return 0;
343 }
344
345 /**
346 * Gets the SIP URI of this profile.
347 *
348 * @return the SIP URI of this profile
Hung-ying Tyan286bb5a2010-09-14 20:43:54 +0800349 * @hide
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800350 */
351 public SipURI getUri() {
352 return (SipURI) mAddress.getURI();
353 }
354
355 /**
356 * Gets the SIP URI string of this profile.
357 *
358 * @return the SIP URI string of this profile
359 */
360 public String getUriString() {
Chung-yih Wangf0532922010-11-03 13:11:53 +0800361 // We need to return the sip uri domain instead of
362 // the SIP URI with transport, port information if
363 // the outbound proxy address exists.
364 if (!TextUtils.isEmpty(mProxyAddress)) {
365 return "sip:" + getUserName() + "@" + mDomain;
366 }
367 return getUri().toString();
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800368 }
369
370 /**
371 * Gets the SIP address of this profile.
372 *
373 * @return the SIP address of this profile
Hung-ying Tyan286bb5a2010-09-14 20:43:54 +0800374 * @hide
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800375 */
376 public Address getSipAddress() {
377 return mAddress;
378 }
379
380 /**
381 * Gets the display name of the user.
382 *
383 * @return the display name of the user
384 */
385 public String getDisplayName() {
386 return mAddress.getDisplayName();
387 }
388
389 /**
390 * Gets the username.
391 *
392 * @return the username
393 */
394 public String getUserName() {
395 return getUri().getUser();
396 }
397
398 /**
Chung-yih Wang0f7de882011-01-06 18:44:43 +0800399 * Gets the username for authentication. If it is null, then the username
Chung-yih Wang9e25df42011-02-10 15:20:41 +0800400 * is used in authentication instead.
Chung-yih Wang0f7de882011-01-06 18:44:43 +0800401 *
Chung-yih Wang9e25df42011-02-10 15:20:41 +0800402 * @return the authentication username
403 * @see #getUserName
Chung-yih Wang0f7de882011-01-06 18:44:43 +0800404 */
405 public String getAuthUserName() {
406 return mAuthUserName;
407 }
408
409 /**
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800410 * Gets the password.
411 *
412 * @return the password
413 */
414 public String getPassword() {
415 return mPassword;
416 }
417
418 /**
419 * Gets the SIP domain.
420 *
421 * @return the SIP domain
422 */
423 public String getSipDomain() {
424 return mDomain;
425 }
426
427 /**
428 * Gets the port number of the SIP server.
429 *
430 * @return the port number of the SIP server
431 */
432 public int getPort() {
Chung-yih Wangf0532922010-11-03 13:11:53 +0800433 return mPort;
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800434 }
435
436 /**
437 * Gets the protocol used to connect to the server.
438 *
439 * @return the protocol
440 */
441 public String getProtocol() {
442 return mProtocol;
443 }
444
445 /**
446 * Gets the network address of the server outbound proxy.
447 *
448 * @return the network address of the server outbound proxy
449 */
450 public String getProxyAddress() {
451 return mProxyAddress;
452 }
453
454 /**
455 * Gets the (user-defined) name of the profile.
456 *
457 * @return name of the profile
458 */
459 public String getProfileName() {
460 return mProfileName;
461 }
462
463 /**
464 * Gets the flag of 'Sending keep-alive'.
465 *
466 * @return the flag of sending SIP keep-alive messages.
467 */
468 public boolean getSendKeepAlive() {
469 return mSendKeepAlive;
470 }
471
472 /**
473 * Gets the flag of 'Auto Registration'.
474 *
475 * @return the flag of registering the profile automatically.
476 */
477 public boolean getAutoRegistration() {
478 return mAutoRegistration;
479 }
Hung-ying Tyancf95f5d2010-08-23 21:36:14 +0800480
481 /**
Chung-yih Wang5424c8d2010-08-25 19:02:18 +0800482 * Sets the calling process's Uid in the sip service.
483 * @hide
484 */
485 public void setCallingUid(int uid) {
486 mCallingUid = uid;
487 }
488
489 /**
490 * Gets the calling process's Uid in the sip settings.
491 * @hide
492 */
493 public int getCallingUid() {
494 return mCallingUid;
495 }
Chung-yih Wangf0532922010-11-03 13:11:53 +0800496
497 private Object readResolve() throws ObjectStreamException {
498 // For compatibility.
499 if (mPort == 0) mPort = DEFAULT_PORT;
500 return this;
501 }
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800502}